blob: 1e86801357b1dc3a90f23c82e134c104990381b3 [file] [log] [blame]
Mike LeBeau92c33522010-01-25 18:18:45 -05001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Mike LeBeau766a19b2010-02-11 22:57:12 -080019import android.content.ComponentName;
Mike LeBeau92c33522010-01-25 18:18:45 -050020import android.content.Intent;
21import android.content.pm.PackageManager;
Mike LeBeau766a19b2010-02-11 22:57:12 -080022import android.content.pm.ResolveInfo;
23import android.content.pm.ServiceInfo;
Dianne Hackborn0382a492010-03-04 11:44:09 -080024import android.content.pm.PackageManager.NameNotFoundException;
25import android.content.res.Resources;
Mike LeBeau766a19b2010-02-11 22:57:12 -080026import android.content.res.TypedArray;
27import android.content.res.XmlResourceParser;
Mike LeBeau766a19b2010-02-11 22:57:12 -080028import android.preference.ListPreference;
Mike LeBeau92c33522010-01-25 18:18:45 -050029import android.preference.Preference;
Mike LeBeau766a19b2010-02-11 22:57:12 -080030import android.preference.PreferenceCategory;
Mike LeBeau92c33522010-01-25 18:18:45 -050031import android.preference.PreferenceGroup;
Mike LeBeau766a19b2010-02-11 22:57:12 -080032import android.preference.PreferenceScreen;
33import android.preference.Preference.OnPreferenceChangeListener;
34import android.provider.Settings;
35import android.speech.RecognitionService;
36import android.util.AttributeSet;
37import android.util.Log;
38import android.util.Xml;
Mike LeBeau92c33522010-01-25 18:18:45 -050039
Mike LeBeau766a19b2010-02-11 22:57:12 -080040import java.io.IOException;
41import java.util.HashMap;
Mike LeBeau92c33522010-01-25 18:18:45 -050042import java.util.List;
43
Amith Yamasanib44161f2010-12-10 13:17:34 -080044import org.xmlpull.v1.XmlPullParser;
45import org.xmlpull.v1.XmlPullParserException;
46
Mike LeBeau92c33522010-01-25 18:18:45 -050047/**
48 * Settings screen for voice input/output.
49 */
Amith Yamasanib44161f2010-12-10 13:17:34 -080050public class VoiceInputOutputSettings implements OnPreferenceChangeListener {
51
Mike LeBeau766a19b2010-02-11 22:57:12 -080052 private static final String TAG = "VoiceInputOutputSettings";
Amith Yamasanib44161f2010-12-10 13:17:34 -080053
Mike LeBeau766a19b2010-02-11 22:57:12 -080054 private static final String KEY_VOICE_INPUT_CATEGORY = "voice_input_category";
55 private static final String KEY_RECOGNIZER = "recognizer";
56 private static final String KEY_RECOGNIZER_SETTINGS = "recognizer_settings";
57
58 private PreferenceGroup mParent;
59 private PreferenceCategory mVoiceInputCategory;
60 private ListPreference mRecognizerPref;
61 private PreferenceScreen mSettingsPref;
Amith Yamasanib44161f2010-12-10 13:17:34 -080062 private SettingsPreferenceFragment mFragment;
63
Mike LeBeau766a19b2010-02-11 22:57:12 -080064 private HashMap<String, ResolveInfo> mAvailableRecognizersMap;
Mike LeBeau92c33522010-01-25 18:18:45 -050065
Amith Yamasanib44161f2010-12-10 13:17:34 -080066 public VoiceInputOutputSettings(SettingsPreferenceFragment fragment) {
67 mFragment = fragment;
68 }
Mike LeBeau766a19b2010-02-11 22:57:12 -080069
Amith Yamasanib44161f2010-12-10 13:17:34 -080070 public void onCreate() {
71
72 mParent = (PreferenceGroup) mFragment.getPreferenceScreen();
Mike LeBeau766a19b2010-02-11 22:57:12 -080073 mVoiceInputCategory = (PreferenceCategory) mParent.findPreference(KEY_VOICE_INPUT_CATEGORY);
Amith Yamasanib44161f2010-12-10 13:17:34 -080074 mRecognizerPref = (ListPreference) mVoiceInputCategory.findPreference(KEY_RECOGNIZER);
Mike LeBeau766a19b2010-02-11 22:57:12 -080075 mRecognizerPref.setOnPreferenceChangeListener(this);
Amith Yamasanib44161f2010-12-10 13:17:34 -080076 mSettingsPref = (PreferenceScreen)
77 mVoiceInputCategory.findPreference(KEY_RECOGNIZER_SETTINGS);
78
Mike LeBeau766a19b2010-02-11 22:57:12 -080079 mAvailableRecognizersMap = new HashMap<String, ResolveInfo>();
Amith Yamasanib44161f2010-12-10 13:17:34 -080080
Mike LeBeau766a19b2010-02-11 22:57:12 -080081 populateOrRemoveRecognizerPreference();
Mike LeBeau92c33522010-01-25 18:18:45 -050082 }
Amith Yamasanib44161f2010-12-10 13:17:34 -080083
Mike LeBeau766a19b2010-02-11 22:57:12 -080084 private void populateOrRemoveRecognizerPreference() {
Amith Yamasanib44161f2010-12-10 13:17:34 -080085 List<ResolveInfo> availableRecognitionServices =
86 mFragment.getPackageManager().queryIntentServices(
Mike LeBeau766a19b2010-02-11 22:57:12 -080087 new Intent(RecognitionService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
88 int numAvailable = availableRecognitionServices.size();
Mike LeBeau92c33522010-01-25 18:18:45 -050089
Mike LeBeau766a19b2010-02-11 22:57:12 -080090 if (numAvailable == 0) {
91 // No recognizer available - remove all related preferences.
Amith Yamasanib44161f2010-12-10 13:17:34 -080092 mFragment.getPreferenceScreen().removePreference(mVoiceInputCategory);
Mike LeBeau766a19b2010-02-11 22:57:12 -080093 } else if (numAvailable == 1) {
Mike LeBeau4c2ffc52010-02-12 14:47:48 -080094 // Only one recognizer available, so don't show the list of choices, but do
95 // set up the link to settings for the available recognizer.
Amith Yamasanib44161f2010-12-10 13:17:34 -080096 mVoiceInputCategory.removePreference(mRecognizerPref);
97
Mike LeBeau4c2ffc52010-02-12 14:47:48 -080098 // But first set up the available recognizers map with just the one recognizer.
99 ResolveInfo resolveInfo = availableRecognitionServices.get(0);
100 String recognizerComponent =
101 new ComponentName(resolveInfo.serviceInfo.packageName,
Mike LeBeaueffc7542010-02-23 14:51:10 -0800102 resolveInfo.serviceInfo.name).flattenToShortString();
103
Mike LeBeau4c2ffc52010-02-12 14:47:48 -0800104 mAvailableRecognizersMap.put(recognizerComponent, resolveInfo);
105
106 String currentSetting = Settings.Secure.getString(
Amith Yamasanib44161f2010-12-10 13:17:34 -0800107 mFragment.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
Mike LeBeau4c2ffc52010-02-12 14:47:48 -0800108 updateSettingsLink(currentSetting);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800109 } else {
110 // Multiple recognizers available, so show the full list of choices.
111 populateRecognizerPreference(availableRecognitionServices);
Mike LeBeau92c33522010-01-25 18:18:45 -0500112 }
Mike LeBeau766a19b2010-02-11 22:57:12 -0800113 }
Amith Yamasanib44161f2010-12-10 13:17:34 -0800114
Mike LeBeau766a19b2010-02-11 22:57:12 -0800115 private void populateRecognizerPreference(List<ResolveInfo> recognizers) {
116 int size = recognizers.size();
117 CharSequence[] entries = new CharSequence[size];
118 CharSequence[] values = new CharSequence[size];
119
120 // Get the current value from the secure setting.
121 String currentSetting = Settings.Secure.getString(
Amith Yamasanib44161f2010-12-10 13:17:34 -0800122 mFragment.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800123
124 // Iterate through all the available recognizers and load up their info to show
125 // in the preference. Also build up a map of recognizer component names to their
126 // ResolveInfos - we'll need that a little later.
127 for (int i = 0; i < size; i++) {
128 ResolveInfo resolveInfo = recognizers.get(i);
129 String recognizerComponent =
130 new ComponentName(resolveInfo.serviceInfo.packageName,
Mike LeBeaueffc7542010-02-23 14:51:10 -0800131 resolveInfo.serviceInfo.name).flattenToShortString();
Mike LeBeau766a19b2010-02-11 22:57:12 -0800132
133 mAvailableRecognizersMap.put(recognizerComponent, resolveInfo);
Mike LeBeau92c33522010-01-25 18:18:45 -0500134
Amith Yamasanib44161f2010-12-10 13:17:34 -0800135 entries[i] = resolveInfo.loadLabel(mFragment.getPackageManager());
Mike LeBeau766a19b2010-02-11 22:57:12 -0800136 values[i] = recognizerComponent;
137 }
138
139 mRecognizerPref.setEntries(entries);
140 mRecognizerPref.setEntryValues(values);
141
142 mRecognizerPref.setDefaultValue(currentSetting);
143 mRecognizerPref.setValue(currentSetting);
144
145 updateSettingsLink(currentSetting);
146 }
147
148 private void updateSettingsLink(String currentSetting) {
149 ResolveInfo currentRecognizer = mAvailableRecognizersMap.get(currentSetting);
150 ServiceInfo si = currentRecognizer.serviceInfo;
151 XmlResourceParser parser = null;
152 String settingsActivity = null;
153 try {
Amith Yamasanib44161f2010-12-10 13:17:34 -0800154 parser = si.loadXmlMetaData(mFragment.getPackageManager(),
155 RecognitionService.SERVICE_META_DATA);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800156 if (parser == null) {
157 throw new XmlPullParserException("No " + RecognitionService.SERVICE_META_DATA +
158 " meta-data for " + si.packageName);
Mike LeBeau92c33522010-01-25 18:18:45 -0500159 }
Mike LeBeau766a19b2010-02-11 22:57:12 -0800160
Amith Yamasanib44161f2010-12-10 13:17:34 -0800161 Resources res = mFragment.getPackageManager().getResourcesForApplication(
Dianne Hackborn0382a492010-03-04 11:44:09 -0800162 si.applicationInfo);
163
Mike LeBeau766a19b2010-02-11 22:57:12 -0800164 AttributeSet attrs = Xml.asAttributeSet(parser);
165
166 int type;
167 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
168 && type != XmlPullParser.START_TAG) {
169 }
170
171 String nodeName = parser.getName();
172 if (!"recognition-service".equals(nodeName)) {
173 throw new XmlPullParserException(
174 "Meta-data does not start with recognition-service tag");
175 }
176
Dianne Hackborn0382a492010-03-04 11:44:09 -0800177 TypedArray array = res.obtainAttributes(attrs,
Mike LeBeau766a19b2010-02-11 22:57:12 -0800178 com.android.internal.R.styleable.RecognitionService);
179 settingsActivity = array.getString(
180 com.android.internal.R.styleable.RecognitionService_settingsActivity);
181 array.recycle();
182 } catch (XmlPullParserException e) {
183 Log.e(TAG, "error parsing recognition service meta-data", e);
184 } catch (IOException e) {
185 Log.e(TAG, "error parsing recognition service meta-data", e);
Dianne Hackborn0382a492010-03-04 11:44:09 -0800186 } catch (NameNotFoundException e) {
187 Log.e(TAG, "error parsing recognition service meta-data", e);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800188 } finally {
189 if (parser != null) parser.close();
Mike LeBeau92c33522010-01-25 18:18:45 -0500190 }
191
Mike LeBeau766a19b2010-02-11 22:57:12 -0800192 if (settingsActivity == null) {
193 // No settings preference available - hide the preference.
194 Log.w(TAG, "no recognizer settings available for " + si.packageName);
195 mSettingsPref.setIntent(null);
Amith Yamasanib44161f2010-12-10 13:17:34 -0800196 mVoiceInputCategory.removePreference(mSettingsPref);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800197 } else {
198 Intent i = new Intent(Intent.ACTION_MAIN);
199 i.setComponent(new ComponentName(si.packageName, settingsActivity));
200 mSettingsPref.setIntent(i);
Amith Yamasanib44161f2010-12-10 13:17:34 -0800201 mRecognizerPref.setSummary(currentRecognizer.loadLabel(mFragment.getPackageManager()));
Mike LeBeau766a19b2010-02-11 22:57:12 -0800202 }
203 }
204
205 public boolean onPreferenceChange(Preference preference, Object newValue) {
206 if (preference == mRecognizerPref) {
207 String setting = (String) newValue;
Amith Yamasanib44161f2010-12-10 13:17:34 -0800208
Mike LeBeau766a19b2010-02-11 22:57:12 -0800209 // Put the new value back into secure settings.
Amith Yamasanib44161f2010-12-10 13:17:34 -0800210 Settings.Secure.putString(mFragment.getContentResolver(),
Mike LeBeau766a19b2010-02-11 22:57:12 -0800211 Settings.Secure.VOICE_RECOGNITION_SERVICE,
212 setting);
Amith Yamasanib44161f2010-12-10 13:17:34 -0800213
Mike LeBeau766a19b2010-02-11 22:57:12 -0800214 // Update the settings item so it points to the right settings.
215 updateSettingsLink(setting);
216 }
217 return true;
Mike LeBeau92c33522010-01-25 18:18:45 -0500218 }
219}