blob: 87e423c627edcc5779f55e71e88b088f1b082a85 [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 org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
22import android.content.ComponentName;
Mike LeBeau92c33522010-01-25 18:18:45 -050023import android.content.Intent;
24import android.content.pm.PackageManager;
Mike LeBeau766a19b2010-02-11 22:57:12 -080025import android.content.pm.ResolveInfo;
26import android.content.pm.ServiceInfo;
27import android.content.res.TypedArray;
28import android.content.res.XmlResourceParser;
Mike LeBeau92c33522010-01-25 18:18:45 -050029import android.os.Bundle;
Mike LeBeau766a19b2010-02-11 22:57:12 -080030import android.preference.ListPreference;
Mike LeBeau92c33522010-01-25 18:18:45 -050031import android.preference.Preference;
32import android.preference.PreferenceActivity;
Mike LeBeau766a19b2010-02-11 22:57:12 -080033import android.preference.PreferenceCategory;
Mike LeBeau92c33522010-01-25 18:18:45 -050034import android.preference.PreferenceGroup;
Mike LeBeau766a19b2010-02-11 22:57:12 -080035import android.preference.PreferenceScreen;
36import android.preference.Preference.OnPreferenceChangeListener;
37import android.provider.Settings;
38import android.speech.RecognitionService;
39import android.util.AttributeSet;
40import android.util.Log;
41import android.util.Xml;
Mike LeBeau92c33522010-01-25 18:18:45 -050042
Mike LeBeau766a19b2010-02-11 22:57:12 -080043import java.io.IOException;
44import java.util.HashMap;
Mike LeBeau92c33522010-01-25 18:18:45 -050045import java.util.List;
46
47/**
48 * Settings screen for voice input/output.
49 */
Mike LeBeau766a19b2010-02-11 22:57:12 -080050public class VoiceInputOutputSettings extends PreferenceActivity
51 implements OnPreferenceChangeListener {
52
53 private static final String TAG = "VoiceInputOutputSettings";
Mike LeBeau92c33522010-01-25 18:18:45 -050054
55 private static final String KEY_PARENT = "parent";
Mike LeBeau766a19b2010-02-11 22:57:12 -080056 private static final String KEY_VOICE_INPUT_CATEGORY = "voice_input_category";
57 private static final String KEY_RECOGNIZER = "recognizer";
58 private static final String KEY_RECOGNIZER_SETTINGS = "recognizer_settings";
59
60 private PreferenceGroup mParent;
61 private PreferenceCategory mVoiceInputCategory;
62 private ListPreference mRecognizerPref;
63 private PreferenceScreen mSettingsPref;
64
65 private HashMap<String, ResolveInfo> mAvailableRecognizersMap;
Mike LeBeau92c33522010-01-25 18:18:45 -050066
67 @Override
68 protected void onCreate(Bundle icicle) {
69 super.onCreate(icicle);
70
71 addPreferencesFromResource(R.xml.voice_input_output_settings);
Mike LeBeau766a19b2010-02-11 22:57:12 -080072
73 mParent = (PreferenceGroup) findPreference(KEY_PARENT);
74 mVoiceInputCategory = (PreferenceCategory) mParent.findPreference(KEY_VOICE_INPUT_CATEGORY);
75 mRecognizerPref = (ListPreference) mParent.findPreference(KEY_RECOGNIZER);
76 mRecognizerPref.setOnPreferenceChangeListener(this);
77 mSettingsPref = (PreferenceScreen) mParent.findPreference(KEY_RECOGNIZER_SETTINGS);
Mike LeBeau92c33522010-01-25 18:18:45 -050078
Mike LeBeau766a19b2010-02-11 22:57:12 -080079 mAvailableRecognizersMap = new HashMap<String, ResolveInfo>();
80
81 populateOrRemoveRecognizerPreference();
Mike LeBeau92c33522010-01-25 18:18:45 -050082 }
Mike LeBeau766a19b2010-02-11 22:57:12 -080083
84 private void populateOrRemoveRecognizerPreference() {
85 List<ResolveInfo> availableRecognitionServices = getPackageManager().queryIntentServices(
86 new Intent(RecognitionService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
87 int numAvailable = availableRecognitionServices.size();
Mike LeBeau92c33522010-01-25 18:18:45 -050088
Mike LeBeau766a19b2010-02-11 22:57:12 -080089 if (numAvailable == 0) {
90 // No recognizer available - remove all related preferences.
91 removePreference(mVoiceInputCategory);
92 removePreference(mRecognizerPref);
93 removePreference(mSettingsPref);
94 } else if (numAvailable == 1) {
Mike LeBeau4c2ffc52010-02-12 14:47:48 -080095 // Only one recognizer available, so don't show the list of choices, but do
96 // set up the link to settings for the available recognizer.
Mike LeBeau766a19b2010-02-11 22:57:12 -080097 removePreference(mRecognizerPref);
Mike LeBeau4c2ffc52010-02-12 14:47:48 -080098
99 // But first set up the available recognizers map with just the one recognizer.
100 ResolveInfo resolveInfo = availableRecognitionServices.get(0);
101 String recognizerComponent =
102 new ComponentName(resolveInfo.serviceInfo.packageName,
Mike LeBeaueffc7542010-02-23 14:51:10 -0800103 resolveInfo.serviceInfo.name).flattenToShortString();
104
Mike LeBeau4c2ffc52010-02-12 14:47:48 -0800105 mAvailableRecognizersMap.put(recognizerComponent, resolveInfo);
106
107 String currentSetting = Settings.Secure.getString(
108 getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
109 updateSettingsLink(currentSetting);
Mike LeBeau766a19b2010-02-11 22:57:12 -0800110 } else {
111 // Multiple recognizers available, so show the full list of choices.
112 populateRecognizerPreference(availableRecognitionServices);
Mike LeBeau92c33522010-01-25 18:18:45 -0500113 }
Mike LeBeau766a19b2010-02-11 22:57:12 -0800114 }
115
116 private void removePreference(Preference pref) {
117 if (pref != null) {
118 mParent.removePreference(pref);
119 }
120 }
121
122 private void populateRecognizerPreference(List<ResolveInfo> recognizers) {
123 int size = recognizers.size();
124 CharSequence[] entries = new CharSequence[size];
125 CharSequence[] values = new CharSequence[size];
126
127 // Get the current value from the secure setting.
128 String currentSetting = Settings.Secure.getString(
129 getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
130
131 // Iterate through all the available recognizers and load up their info to show
132 // in the preference. Also build up a map of recognizer component names to their
133 // ResolveInfos - we'll need that a little later.
134 for (int i = 0; i < size; i++) {
135 ResolveInfo resolveInfo = recognizers.get(i);
136 String recognizerComponent =
137 new ComponentName(resolveInfo.serviceInfo.packageName,
Mike LeBeaueffc7542010-02-23 14:51:10 -0800138 resolveInfo.serviceInfo.name).flattenToShortString();
Mike LeBeau766a19b2010-02-11 22:57:12 -0800139
140 mAvailableRecognizersMap.put(recognizerComponent, resolveInfo);
Mike LeBeau92c33522010-01-25 18:18:45 -0500141
Mike LeBeau766a19b2010-02-11 22:57:12 -0800142 entries[i] = resolveInfo.loadLabel(getPackageManager());
143 values[i] = recognizerComponent;
144 }
145
146 mRecognizerPref.setEntries(entries);
147 mRecognizerPref.setEntryValues(values);
148
149 mRecognizerPref.setDefaultValue(currentSetting);
150 mRecognizerPref.setValue(currentSetting);
151
152 updateSettingsLink(currentSetting);
153 }
154
155 private void updateSettingsLink(String currentSetting) {
156 ResolveInfo currentRecognizer = mAvailableRecognizersMap.get(currentSetting);
157 ServiceInfo si = currentRecognizer.serviceInfo;
158 XmlResourceParser parser = null;
159 String settingsActivity = null;
160 try {
161 parser = si.loadXmlMetaData(getPackageManager(), RecognitionService.SERVICE_META_DATA);
162 if (parser == null) {
163 throw new XmlPullParserException("No " + RecognitionService.SERVICE_META_DATA +
164 " meta-data for " + si.packageName);
Mike LeBeau92c33522010-01-25 18:18:45 -0500165 }
Mike LeBeau766a19b2010-02-11 22:57:12 -0800166
167 AttributeSet attrs = Xml.asAttributeSet(parser);
168
169 int type;
170 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
171 && type != XmlPullParser.START_TAG) {
172 }
173
174 String nodeName = parser.getName();
175 if (!"recognition-service".equals(nodeName)) {
176 throw new XmlPullParserException(
177 "Meta-data does not start with recognition-service tag");
178 }
179
180 TypedArray array = getResources().obtainAttributes(attrs,
181 com.android.internal.R.styleable.RecognitionService);
182 settingsActivity = array.getString(
183 com.android.internal.R.styleable.RecognitionService_settingsActivity);
184 array.recycle();
185 } catch (XmlPullParserException e) {
186 Log.e(TAG, "error parsing recognition service meta-data", e);
187 } catch (IOException e) {
188 Log.e(TAG, "error parsing recognition service meta-data", e);
189 } finally {
190 if (parser != null) parser.close();
Mike LeBeau92c33522010-01-25 18:18:45 -0500191 }
192
Mike LeBeau766a19b2010-02-11 22:57:12 -0800193 if (settingsActivity == null) {
194 // No settings preference available - hide the preference.
195 Log.w(TAG, "no recognizer settings available for " + si.packageName);
196 mSettingsPref.setIntent(null);
197 mParent.removePreference(mSettingsPref);
198 } else {
199 Intent i = new Intent(Intent.ACTION_MAIN);
200 i.setComponent(new ComponentName(si.packageName, settingsActivity));
201 mSettingsPref.setIntent(i);
Mike LeBeau4c2ffc52010-02-12 14:47:48 -0800202 mRecognizerPref.setSummary(currentRecognizer.loadLabel(getPackageManager()));
Mike LeBeau766a19b2010-02-11 22:57:12 -0800203 }
204 }
205
206 public boolean onPreferenceChange(Preference preference, Object newValue) {
207 if (preference == mRecognizerPref) {
208 String setting = (String) newValue;
209
210 // Put the new value back into secure settings.
211 Settings.Secure.putString(
212 getContentResolver(),
213 Settings.Secure.VOICE_RECOGNITION_SERVICE,
214 setting);
215
216 // Update the settings item so it points to the right settings.
217 updateSettingsLink(setting);
218 }
219 return true;
Mike LeBeau92c33522010-01-25 18:18:45 -0500220 }
221}