<string name="vision_settings_title">Vision Settings</string>
<!-- Settings description for a brief version of Vision-Related Accessibility Settings. Tells the user that they can adjust these settings now to help them through the remainder of the Setup Wizard and that they can later be changed in Settings. Displayed in Setup Wizard only. [CHAR LIMIT=none] -->
<string name="vision_settings_description">You can customize this device to fit your needs. These accessibility features can be changed later in Settings.</string>
- <!-- Title for the accessibility preference category of accessibility services. [CHAR LIMIT=25] -->
- <string name="accessibility_services_title">Services</string>
+ <!-- Title for the accessibility preference category of screen reader services and settings. [CHAR LIMIT=50] -->
+ <string name="screen_reader_category_title">Screen readers</string>
+ <!-- Title for the accessibility preference category of audio services and settings. [CHAR LIMIT=50] -->
+ <string name="audio_and_captions_category_title">Audio & on-screen text</string>
+ <!-- Title for the accessibility preference category of display services and settings. [CHAR LIMIT=50] -->
+ <string name="display_category_title">Display</string>
+ <!-- Title for the accessibility preference category of interaction control services and settings. [CHAR LIMIT=50] -->
+ <string name="interaction_control_category_title">Interaction controls</string>
+ <!-- Title for the accessibility preference category of services downloaded by the user. [CHAR LIMIT=50] -->
+ <string name="user_installed_services_category_title">Downloaded services</string>
<!-- Title for the Talkback Accessibility Service. Displayed on the Accessibility Settings screen in Setup Wizard. [CHAR_LIMIT=25] -->
<string name="talkback_title">Talkback</string>
<!-- Summary for the Talkback Accessibility Service. Lets the user know that Talkback is a screenreader and that it is usually most helpful to blind and low vision users and whether the service is on. [CHAR_LIMIT=none] -->
<string name="talkback_summary">Screen reader primarily for people with blindness and low vision</string>
<!-- Summary for the Select to Speak Accessibility Service. [CHAR_LIMIT=none] -->
<string name="select_to_speak_summary">Tap items on your screen to hear them read aloud</string>
- <!-- Title for the accessibility preference category of system related preferences. [CHAR LIMIT=25] -->
- <string name="accessibility_system_title">System</string>
- <!-- Title for the accessibility preference category of display related preferences. [CHAR LIMIT=25] -->
- <string name="accessibility_display_title">Display</string>
<!-- Title for the accessibility preference screen to enable video captioning. [CHAR LIMIT=35] -->
<string name="accessibility_captioning_title">Captions</string>
<!-- Title for the accessibility preference screen to enable screen magnification. [CHAR LIMIT=35] -->
<string name="disable_service_message">Tapping OK will
stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>.</string>
- <!-- Title for the prompt shown as a placeholder if no accessibility serivices are installed. [CHAR LIMIT=50] -->
+ <!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
<string name="accessibility_no_services_installed">No services installed</string>
- <!-- Default description for an accessibility serivice if the latter doesn't provide one. [CHAR LIMIT=NONE] -->
+ <!-- Default description for an accessibility service if the latter doesn't provide one. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_default_description">No description provided.</string>
<!-- Accessibility settings: button for lauching settings for an accessibility service -->
<!-- Title for print service settings screen [CHAR LIMIT=25] -->
<string name="print_settings_title">Print services</string>
- <!-- Title for the prompt shown as a placeholder if no print serivices are installed. [CHAR LIMIT=50] -->
+ <!-- Title for the prompt shown as a placeholder if no print services are installed. [CHAR LIMIT=50] -->
<string name="print_no_services_installed">No services installed</string>
<!-- Title for the prompt shown as a placeholder if no printers are found while searching. [CHAR LIMIT=50] -->
android:title="@string/accessibility_settings"
android:persistent="true">
+ <ListPreference
+ android:key="accessibility_shortcut_preference"
+ android:title="@string/accessibility_global_gesture_preference_title"/>
+
<PreferenceCategory
- android:key="services_category"
- android:title="@string/accessibility_services_title">
+ android:key="user_installed_services_category"
+ android:title="@string/user_installed_services_category_title">
</PreferenceCategory>
<PreferenceCategory
- android:key="system_category"
- android:title="@string/accessibility_system_title">
+ android:key="screen_reader_category"
+ android:title="@string/screen_reader_category_title">
<Preference
- android:fragment="com.android.settings.accessibility.CaptionPropertiesFragment"
- android:key="captioning_preference_screen"
- android:title="@string/accessibility_captioning_title" />
+ android:key="tts_settings_preference"
+ android:fragment="com.android.settings.tts.TextToSpeechSettings"
+ android:title="@string/tts_settings_title"/>
+ </PreferenceCategory>
- <Preference
- android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
- android:key="screen_magnification_preference_screen"
- android:title="@string/accessibility_screen_magnification_title"/>
+ <PreferenceCategory
+ android:key="display_category"
+ android:title="@string/display_category_title">
<Preference
- android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
- android:key="font_size_preference_screen"
- android:title="@string/title_font_size"/>
+ android:fragment="com.android.settings.accessibility.ToggleFontSizePreferenceFragment"
+ android:key="font_size_preference_screen"
+ android:title="@string/title_font_size"/>
<com.android.settings.display.ScreenZoomPreference
- android:key="screen_zoom"
- android:title="@string/screen_zoom_title"/>
+ android:key="screen_zoom"
+ android:title="@string/screen_zoom_title"/>
<Preference
- android:fragment="com.android.settings.accessibility.ToggleAutoclickPreferenceFragment"
- android:key="autoclick_preference_screen"
- android:title="@string/accessibility_autoclick_preference_title"/>
+ android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
+ android:key="screen_magnification_preference_screen"
+ android:title="@string/accessibility_screen_magnification_title"/>
<SwitchPreference
android:key="toggle_high_text_contrast_preference"
android:summary="@string/experimental_preference"/>
<SwitchPreference
- android:key="toggle_power_button_ends_call_preference"
- android:title="@string/accessibility_power_button_ends_call_prerefence_title"
- android:persistent="false"/>
+ android:key="toggle_inversion_preference"
+ android:title="@string/accessibility_display_inversion_preference_title"
+ android:summary="@string/accessibility_display_inversion_preference_subtitle"
+ android:persistent="false" />
- <SwitchPreference
- android:key="toggle_lock_screen_rotation_preference"
- android:title="@string/accelerometer_title"
- android:persistent="false"/>
+ <Preference
+ android:fragment="com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment"
+ android:key="daltonizer_preference_screen"
+ android:title="@string/accessibility_display_daltonizer_preference_title" />
<SwitchPreference
android:key="toggle_large_pointer_icon"
android:title="@string/accessibility_toggle_large_pointer_icon_title" />
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="interaction_control_category"
+ android:title="@string/interaction_control_category_title">
+
+ <Preference
+ android:fragment="com.android.settings.accessibility.ToggleAutoclickPreferenceFragment"
+ android:key="autoclick_preference_screen"
+ android:title="@string/accessibility_autoclick_preference_title"/>
<SwitchPreference
- android:key="toggle_master_mono"
- android:title="@string/accessibility_toggle_master_mono_title"
- android:summary="@string/accessibility_toggle_master_mono_summary"
+ android:key="toggle_power_button_ends_call_preference"
+ android:title="@string/accessibility_power_button_ends_call_prerefence_title"
android:persistent="false"/>
- <ListPreference
- android:key="accessibility_shortcut_preference"
- android:title="@string/accessibility_global_gesture_preference_title"/>
-
- <Preference
- android:key="tts_settings_preference"
- android:fragment="com.android.settings.tts.TextToSpeechSettings"
- android:title="@string/tts_settings_title"/>
+ <SwitchPreference
+ android:key="toggle_lock_screen_rotation_preference"
+ android:title="@string/accelerometer_title"
+ android:persistent="false"/>
- <ListPreference android:key="select_long_press_timeout_preference"
+ <ListPreference
+ android:key="select_long_press_timeout_preference"
android:title="@string/accessibility_long_press_timeout_preference_title"
android:entries="@array/long_press_timeout_selector_titles"
android:entryValues="@array/long_press_timeout_selector_values"
android:persistent="false"/>
-
</PreferenceCategory>
<PreferenceCategory
- android:key="display_category"
- android:title="@string/accessibility_display_title" >
+ android:key="audio_and_captions_category"
+ android:title="@string/audio_and_captions_category_title">
+
<SwitchPreference
- android:key="toggle_inversion_preference"
- android:title="@string/accessibility_display_inversion_preference_title"
- android:summary="@string/accessibility_display_inversion_preference_subtitle"
- android:persistent="false" />
+ android:key="toggle_master_mono"
+ android:title="@string/accessibility_toggle_master_mono_title"
+ android:summary="@string/accessibility_toggle_master_mono_summary"
+ android:persistent="false"/>
+
<Preference
- android:fragment="com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment"
- android:key="daltonizer_preference_screen"
- android:title="@string/accessibility_display_daltonizer_preference_title" />
+ android:fragment="com.android.settings.accessibility.CaptionPropertiesFragment"
+ android:key="captioning_preference_screen"
+ android:title="@string/accessibility_captioning_title" />
</PreferenceCategory>
-
</PreferenceScreen>
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.view.RotationPolicy.RotationPolicyListener;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.SingleLineSummaryPreference;
import com.android.settings.Utils;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.accessibility.AccessibilityUtils;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class AccessibilitySettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener, Indexable {
+ // Index of the first preference in a preference category.
+ private static final int FIRST_PREFERENCE_IN_CATEGORY_INDEX = 0;
+
// Preference categories
- private static final String SERVICES_CATEGORY = "services_category";
- private static final String SYSTEM_CATEGORY = "system_category";
+ private static final String CATEGORY_SCREEN_READER = "screen_reader_category";
+ private static final String CATEGORY_AUDIO_AND_CAPTIONS = "audio_and_captions_category";
+ private static final String CATEGORY_DISPLAY = "display_category";
+ private static final String CATEGORY_INTERACTION_CONTROL = "interaction_control_category";
+ private static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";
+
+ private static final String[] CATEGORIES = new String[] {
+ CATEGORY_SCREEN_READER, CATEGORY_AUDIO_AND_CAPTIONS, CATEGORY_DISPLAY,
+ CATEGORY_INTERACTION_CONTROL, CATEGORY_DOWNLOADED_SERVICES
+ };
// Preferences
private static final String TOGGLE_HIGH_TEXT_CONTRAST_PREFERENCE =
// ID for dialog that confirms shortcut capabilities
private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
- // Auxiliary members.
- static final Set<ComponentName> sInstalledServices = new HashSet<>();
-
- private final Map<String, String> mLongPressTimeoutValuetoTitleMap = new HashMap<>();
+ private final Map<String, String> mLongPressTimeoutValueToTitleMap = new HashMap<>();
private final Handler mHandler = new Handler();
@Override
public void run() {
if (getActivity() != null) {
- updateServicesPreferences();
+ updateServicePreferences();
}
}
};
new SettingsContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
- updateServicesPreferences();
+ updateServicePreferences();
}
};
}
};
- // Preference controls.
- private PreferenceCategory mServicesCategory;
- private PreferenceCategory mSystemsCategory;
+ private final Map<String, PreferenceCategory> mCategoryToPrefCategoryMap =
+ new ArrayMap<>();
+ private final Map<Preference, PreferenceCategory> mServicePreferenceToPreferenceCategoryMap =
+ new ArrayMap<>();
+ private final Map<ComponentName, PreferenceCategory> mPreBundledServiceComponentToCategoryMap =
+ new ArrayMap<>();
private SwitchPreference mToggleHighTextContrastPreference;
private SwitchPreference mTogglePowerButtonEndsCallPreference;
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.LONG_PRESS_TIMEOUT, Integer.parseInt(stringValue));
mSelectLongPressTimeoutPreference.setSummary(
- mLongPressTimeoutValuetoTitleMap.get(stringValue));
+ mLongPressTimeoutValueToTitleMap.get(stringValue));
}
private void handleToggleInversionPreferenceChange(boolean checked) {
}
private void initializeAllPreferences() {
- mServicesCategory = (PreferenceCategory) findPreference(SERVICES_CATEGORY);
- mSystemsCategory = (PreferenceCategory) findPreference(SYSTEM_CATEGORY);
+ for (int i = 0; i < CATEGORIES.length; i++) {
+ PreferenceCategory prefCategory = (PreferenceCategory) findPreference(CATEGORIES[i]);
+ mCategoryToPrefCategoryMap.put(CATEGORIES[i], prefCategory);
+ }
// Text contrast.
mToggleHighTextContrastPreference =
(SwitchPreference) findPreference(TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE);
if (!KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
|| !Utils.isVoiceCapable(getActivity())) {
- mSystemsCategory.removePreference(mTogglePowerButtonEndsCallPreference);
+ mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL)
+ .removePreference(mTogglePowerButtonEndsCallPreference);
}
// Lock screen rotation.
mToggleLockScreenRotationPreference =
(SwitchPreference) findPreference(TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE);
if (!RotationPolicy.isRotationSupported(getActivity())) {
- mSystemsCategory.removePreference(mToggleLockScreenRotationPreference);
+ mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL)
+ .removePreference(mToggleLockScreenRotationPreference);
}
// Large pointer icon.
mSelectLongPressTimeoutPreference =
(ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
mSelectLongPressTimeoutPreference.setOnPreferenceChangeListener(this);
- if (mLongPressTimeoutValuetoTitleMap.size() == 0) {
+ if (mLongPressTimeoutValueToTitleMap.size() == 0) {
String[] timeoutValues = getResources().getStringArray(
R.array.long_press_timeout_selector_values);
mLongPressTimeoutDefault = Integer.parseInt(timeoutValues[0]);
R.array.long_press_timeout_selector_titles);
final int timeoutValueCount = timeoutValues.length;
for (int i = 0; i < timeoutValueCount; i++) {
- mLongPressTimeoutValuetoTitleMap.put(timeoutValues[i], timeoutTitles[i]);
+ mLongPressTimeoutValueToTitleMap.put(timeoutValues[i], timeoutTitles[i]);
}
}
}
private void updateAllPreferences() {
- updateServicesPreferences();
updateSystemPreferences();
+ updateServicePreferences();
}
- private void updateServicesPreferences() {
+ private void updateServicePreferences() {
// 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
// the global accessibility state to decided whether it is enabled.
// Generate.
- mServicesCategory.removeAll();
+ ArrayList<Preference> servicePreferences =
+ new ArrayList<>(mServicePreferenceToPreferenceCategoryMap.keySet());
+ for (int i = 0; i < servicePreferences.size(); i++) {
+ Preference service = servicePreferences.get(i);
+ PreferenceCategory category = mServicePreferenceToPreferenceCategoryMap.get(service);
+ category.removePreference(service);
+ }
+
+ initializePreBundledServicesMapFromArray(CATEGORY_SCREEN_READER,
+ R.array.config_preinstalled_screen_reader_services);
+ initializePreBundledServicesMapFromArray(CATEGORY_AUDIO_AND_CAPTIONS,
+ R.array.config_preinstalled_audio_and_caption_services);
+ initializePreBundledServicesMapFromArray(CATEGORY_DISPLAY,
+ R.array.config_preinstalled_display_services);
+ initializePreBundledServicesMapFromArray(CATEGORY_INTERACTION_CONTROL,
+ R.array.config_preinstalled_interaction_control_services);
AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getActivity());
final boolean accessibilityEnabled = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
+ PreferenceCategory downloadedServicesCategory =
+ mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
+ // Temporarily add the downloaded services category back if it was previously removed.
+ if (findPreference(CATEGORY_DOWNLOADED_SERVICES) == null) {
+ getPreferenceScreen().addPreference(downloadedServicesCategory);
+ }
+
for (int i = 0, count = installedServices.size(); i < count; ++i) {
AccessibilityServiceInfo info = installedServices.get(i);
- RestrictedPreference preference =
- new RestrictedPreference(mServicesCategory.getContext());
+ SingleLineSummaryPreference preference =
+ new SingleLineSummaryPreference(downloadedServicesCategory.getContext(), null);
String title = info.getResolveInfo().loadLabel(getPackageManager()).toString();
+ Drawable icon = info.getResolveInfo().loadIcon(getPackageManager());
+ if (icon == null) {
+ // todo (saigem): add a default
+ }
+
ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
- ComponentName componentName = new ComponentName(serviceInfo.packageName,
- serviceInfo.name);
+ String packageName = serviceInfo.packageName;
+ ComponentName componentName = new ComponentName(packageName, serviceInfo.name);
+ String componentNameKey = componentName.flattenToString();
preference.setKey(componentName.flattenToString());
preference.setTitle(title);
+ preference.setIcon(icon);
final boolean serviceEnabled = accessibilityEnabled
&& enabledServices.contains(componentName);
- String serviceEnabledString;
- if (serviceEnabled) {
- serviceEnabledString = getString(R.string.accessibility_feature_state_on);
- } else {
- serviceEnabledString = getString(R.string.accessibility_feature_state_off);
- }
+ String serviceState = serviceEnabled ?
+ getString(R.string.accessibility_feature_state_on) :
+ getString(R.string.accessibility_feature_state_off);
+ String serviceSummary = info.loadSummary(getPackageManager());
+ serviceSummary = (TextUtils.isEmpty(serviceSummary)) ? serviceState.toUpperCase() :
+ serviceState.toUpperCase() + " / " + serviceSummary;
// Disable all accessibility services that are not permitted.
- String packageName = serviceInfo.packageName;
boolean serviceAllowed =
permittedServices == null || permittedServices.contains(packageName);
if (!serviceAllowed && !serviceEnabled) {
EnforcedAdmin admin = RestrictedLockUtils.checkIfAccessibilityServiceDisallowed(
- getActivity(), serviceInfo.packageName, UserHandle.myUserId());
+ getActivity(), packageName, UserHandle.myUserId());
if (admin != null) {
preference.setDisabledByAdmin(admin);
} else {
preference.setEnabled(true);
}
- preference.setSummary(serviceEnabledString);
-
- preference.setOrder(i);
+ preference.setSummary(serviceSummary);
preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
preference.setPersistent(true);
extras.putString(EXTRA_SETTINGS_TITLE,
getString(R.string.accessibility_menu_item_settings));
extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
- new ComponentName(info.getResolveInfo().serviceInfo.packageName,
- settingsClassName).flattenToString());
+ new ComponentName(packageName, settingsClassName).flattenToString());
}
-
extras.putParcelable(EXTRA_COMPONENT_NAME, componentName);
- mServicesCategory.addPreference(preference);
+ PreferenceCategory prefCategory = downloadedServicesCategory;
+ // Set the appropriate category if the service comes pre-installed.
+ if (mPreBundledServiceComponentToCategoryMap.containsKey(componentName)) {
+ prefCategory = mPreBundledServiceComponentToCategoryMap.get(componentName);
+ }
+ preference.setOrder(FIRST_PREFERENCE_IN_CATEGORY_INDEX);
+ prefCategory.addPreference(preference);
+ mServicePreferenceToPreferenceCategoryMap.put(preference, prefCategory);
}
- if (mServicesCategory.getPreferenceCount() == 0) {
- if (mNoServicesMessagePreference == null) {
- mNoServicesMessagePreference = new Preference(getPrefContext());
- mNoServicesMessagePreference.setPersistent(false);
- mNoServicesMessagePreference.setLayoutResource(
- R.layout.text_description_preference);
- mNoServicesMessagePreference.setSelectable(false);
- mNoServicesMessagePreference.setSummary(
- getString(R.string.accessibility_no_services_installed));
- }
- mServicesCategory.addPreference(mNoServicesMessagePreference);
+ // If the user has not installed any additional services, hide the category.
+ if (downloadedServicesCategory.getPreferenceCount() == 0) {
+ PreferenceScreen screen = getPreferenceScreen();
+ screen.removePreference(downloadedServicesCategory);
+ }
+ }
+
+ private void initializePreBundledServicesMapFromArray(String categoryKey, int key) {
+ String[] services = getResources().getStringArray(key);
+ PreferenceCategory category = mCategoryToPrefCategoryMap.get(categoryKey);
+ for (int i = 0; i < services.length; i++) {
+ ComponentName component = ComponentName.unflattenFromString(services[i]);
+ mPreBundledServiceComponentToCategoryMap.put(component, category);
}
}
Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault);
String value = String.valueOf(longPressTimeout);
mSelectLongPressTimeoutPreference.setValue(value);
- mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValuetoTitleMap.get(value));
+ mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValueToTitleMap.get(value));
updateFeatureSummary(Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
mCaptioningPreferenceScreen);