TtsEngines.java revision d3ee2fa18464fb7e4d7f6d27610fbf60b6d1ffce
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.speech.tts; 17 18import android.content.Context; 19import android.content.Intent; 20import android.content.pm.ApplicationInfo; 21import android.content.pm.PackageManager; 22import android.content.pm.ResolveInfo; 23import android.content.pm.ServiceInfo; 24import android.provider.Settings; 25import android.speech.tts.TextToSpeech.Engine; 26import android.speech.tts.TextToSpeech.EngineInfo; 27import android.text.TextUtils; 28 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.Comparator; 32import java.util.List; 33 34/** 35 * Support class for querying the list of available engines 36 * on the device and deciding which one to use etc. 37 * 38 * Comments in this class the use the shorthand "system engines" for engines that 39 * are a part of the system image. 40 * 41 * @hide 42 */ 43public class TtsEngines { 44 private final Context mContext; 45 46 public TtsEngines(Context ctx) { 47 mContext = ctx; 48 } 49 50 /** 51 * @return the default TTS engine. If the user has set a default, that 52 * value is returned else the highest ranked engine is returned, 53 * as per {@link EngineInfoComparator}. 54 */ 55 public String getDefaultEngine() { 56 String engine = Settings.Secure.getString(mContext.getContentResolver(), 57 Settings.Secure.TTS_DEFAULT_SYNTH); 58 return engine != null ? engine : getHighestRankedEngineName(); 59 } 60 61 /** 62 * @return the package name of the highest ranked system engine, {@code null} 63 * if no TTS engines were present in the system image. 64 */ 65 public String getHighestRankedEngineName() { 66 final List<EngineInfo> engines = getEngines(); 67 68 if (engines.size() > 0 && engines.get(0).system) { 69 return engines.get(0).name; 70 } 71 72 return null; 73 } 74 75 /** 76 * Returns the engine info for a given engine name. Note that engines are 77 * identified by their package name. 78 */ 79 public EngineInfo getEngineInfo(String packageName) { 80 PackageManager pm = mContext.getPackageManager(); 81 Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE); 82 intent.setPackage(packageName); 83 List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 84 PackageManager.MATCH_DEFAULT_ONLY); 85 // Note that the current API allows only one engine per 86 // package name. Since the "engine name" is the same as 87 // the package name. 88 if (resolveInfos != null && resolveInfos.size() == 1) { 89 return getEngineInfo(resolveInfos.get(0), pm); 90 } 91 92 return null; 93 } 94 95 /** 96 * Gets a list of all installed TTS engines. 97 * 98 * @return A list of engine info objects. The list can be empty, but never {@code null}. 99 */ 100 public List<EngineInfo> getEngines() { 101 PackageManager pm = mContext.getPackageManager(); 102 Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE); 103 List<ResolveInfo> resolveInfos = 104 pm.queryIntentServices(intent, PackageManager.MATCH_DEFAULT_ONLY); 105 if (resolveInfos == null) return Collections.emptyList(); 106 107 List<EngineInfo> engines = new ArrayList<EngineInfo>(resolveInfos.size()); 108 109 for (ResolveInfo resolveInfo : resolveInfos) { 110 EngineInfo engine = getEngineInfo(resolveInfo, pm); 111 if (engine != null) { 112 engines.add(engine); 113 } 114 } 115 Collections.sort(engines, EngineInfoComparator.INSTANCE); 116 117 return engines; 118 } 119 120 /** 121 * Checks whether a given engine is enabled or not. Note that all system 122 * engines are enabled by default. 123 */ 124 public boolean isEngineEnabled(String engine) { 125 // System engines are enabled by default always. 126 EngineInfo info = getEngineInfo(engine); 127 if (info != null && info.system) { 128 return true; 129 } 130 131 for (String enabled : getUserEnabledEngines()) { 132 if (engine.equals(enabled)) { 133 return true; 134 } 135 } 136 return false; 137 } 138 139 private boolean isSystemEngine(ServiceInfo info) { 140 final ApplicationInfo appInfo = info.applicationInfo; 141 return appInfo != null && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 142 } 143 144 private EngineInfo getEngineInfo(ResolveInfo resolve, PackageManager pm) { 145 ServiceInfo service = resolve.serviceInfo; 146 if (service != null) { 147 EngineInfo engine = new EngineInfo(); 148 // Using just the package name isn't great, since it disallows having 149 // multiple engines in the same package, but that's what the existing API does. 150 engine.name = service.packageName; 151 CharSequence label = service.loadLabel(pm); 152 engine.label = TextUtils.isEmpty(label) ? engine.name : label.toString(); 153 engine.icon = service.getIconResource(); 154 engine.priority = resolve.priority; 155 engine.system = isSystemEngine(service); 156 return engine; 157 } 158 159 return null; 160 } 161 162 // Note that in addition to this list, all engines that are a part 163 // of the system are enabled by default. 164 private String[] getUserEnabledEngines() { 165 String str = Settings.Secure.getString(mContext.getContentResolver(), 166 Settings.Secure.TTS_ENABLED_PLUGINS); 167 if (TextUtils.isEmpty(str)) { 168 return new String[0]; 169 } 170 return str.split(" "); 171 } 172 173 private static class EngineInfoComparator implements Comparator<EngineInfo> { 174 private EngineInfoComparator() { } 175 176 static EngineInfoComparator INSTANCE = new EngineInfoComparator(); 177 178 /** 179 * Engines that are a part of the system image are always lesser 180 * than those that are not. Within system engines / non system engines 181 * the engines are sorted in order of their declared priority. 182 */ 183 @Override 184 public int compare(EngineInfo lhs, EngineInfo rhs) { 185 if (lhs.system && !rhs.system) { 186 return -1; 187 } else if (rhs.system && !lhs.system) { 188 return 1; 189 } else { 190 // Either both system engines, or both non system 191 // engines. 192 // 193 // Note, this isn't a typo. Higher priority numbers imply 194 // higher priority, but are "lower" in the sort order. 195 return rhs.priority - lhs.priority; 196 } 197 } 198 } 199 200} 201