diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index c44a796082b6f..14eb084ce4c61 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -231,4 +231,113 @@ No defaults set + + + Text-to-speech settings + + Text-to-speech output + + Speech rate + + Speed at which the text is spoken + + Language + + Use system language + + Language not selected + + Sets the language-specific voice for the spoken text + + Listen to an example + + Play a short demonstration of speech synthesis + + Install voice data + + Install the voice data required for speech synthesis + + This speech synthesis engine may be able to collect + all the text that will be spoken, including personal data like passwords and credit + card numbers. It comes from the %s engine. + Enable the use of this speech synthesis engine? + + This language requires a working network connection for text-to-speech output. + + This is an example of speech synthesis + + Default language status + + %1$s is fully supported + + %1$s requires network connection + + %1$s is not supported + + Checking… + + Settings for %s + + Launch engine settings + + Preferred engine + + General + + + + Very slow + Slow + Normal + Fast + Faster + Very fast + Rapid + Very rapid + Fastest + + + + 60 + 80 + 100 + 150 + 200 + 250 + 300 + 350 + 400 + + + + + This is an example of speech synthesis in English. + Voici un échantillon de synthèse vocale en français. + Dies ist ein Beispiel für Sprachsynthese in Deutsch. + Questo è un esempio di sintesi vocale in italiano. + Este es un ejemplo de síntesis de voz en español. + 이것은 한국어 음성 합성의 예입니다. + + + + eng + fra + deu + ita + spa + kor + + diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java index cf17ea5ebf1a8..99bd4ad1d3dc2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java @@ -16,15 +16,20 @@ package com.android.settingslib.accessibility; +import android.accessibilityservice.AccessibilityServiceInfo; import android.content.ComponentName; import android.content.Context; +import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArraySet; +import android.view.accessibility.AccessibilityManager; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -45,7 +50,7 @@ public class AccessibilityUtils { return Collections.emptySet(); } - final Set enabledServices = new HashSet(); + final Set enabledServices = new HashSet<>(); final TextUtils.SimpleStringSplitter colonSplitter = sStringColonSplitter; colonSplitter.setString(enabledServicesSetting); @@ -71,4 +76,79 @@ public class AccessibilityUtils { final Context langContext = context.createConfigurationContext(config); return langContext.getText(resId); } + + public static void setAccessibilityServiceState(Context context, ComponentName toggledService, + boolean enabled) { + // Parse the enabled services. + Set enabledServices = AccessibilityUtils.getEnabledServicesFromSettings( + context); + + if (enabledServices.isEmpty()) { + enabledServices = new ArraySet<>(1); + } + + // Determine enabled services and accessibility state. + boolean accessibilityEnabled = false; + if (enabled) { + enabledServices.add(toggledService); + // Enabling at least one service enables accessibility. + accessibilityEnabled = true; + } else { + enabledServices.remove(toggledService); + // Check how many enabled and installed services are present. + Set installedServices = getInstalledServices(context); + for (ComponentName enabledService : enabledServices) { + if (installedServices.contains(enabledService)) { + // Disabling the last service disables accessibility. + accessibilityEnabled = true; + break; + } + } + } + + // Update the enabled services setting. + StringBuilder enabledServicesBuilder = new StringBuilder(); + // Keep the enabled services even if they are not installed since we + // have no way to know whether the application restore process has + // completed. In general the system should be responsible for the + // clean up not settings. + for (ComponentName enabledService : enabledServices) { + enabledServicesBuilder.append(enabledService.flattenToString()); + enabledServicesBuilder.append( + AccessibilityUtils.ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR); + } + final int enabledServicesBuilderLength = enabledServicesBuilder.length(); + if (enabledServicesBuilderLength > 0) { + enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1); + } + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + enabledServicesBuilder.toString()); + + // Update accessibility enabled. + Settings.Secure.putInt(context.getContentResolver(), + Settings.Secure.ACCESSIBILITY_ENABLED, accessibilityEnabled ? 1 : 0); + } + + private static Set getInstalledServices(Context context) { + final Set installedServices = new HashSet<>(); + installedServices.clear(); + + final List installedServiceInfos = + AccessibilityManager.getInstance(context) + .getInstalledAccessibilityServiceList(); + if (installedServiceInfos == null) { + return installedServices; + } + + for (final AccessibilityServiceInfo info : installedServiceInfos) { + final ResolveInfo resolveInfo = info.getResolveInfo(); + final ComponentName installedService = new ComponentName( + resolveInfo.serviceInfo.packageName, + resolveInfo.serviceInfo.name); + installedServices.add(installedService); + } + return installedServices; + } + }