diff options
Diffstat (limited to 'src/com/android/settings/voice/VoiceInputHelper.java')
-rw-r--r-- | src/com/android/settings/voice/VoiceInputHelper.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/com/android/settings/voice/VoiceInputHelper.java b/src/com/android/settings/voice/VoiceInputHelper.java new file mode 100644 index 0000000..63b891a --- /dev/null +++ b/src/com/android/settings/voice/VoiceInputHelper.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.voice; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.provider.Settings; +import android.service.voice.VoiceInteractionService; +import android.service.voice.VoiceInteractionServiceInfo; +import android.speech.RecognitionService; +import android.util.ArraySet; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class VoiceInputHelper { + static final String TAG = "VoiceInputHelper"; + final Context mContext; + + final List<ResolveInfo> mAvailableVoiceInteractions; + final List<ResolveInfo> mAvailableRecognition; + + static public class BaseInfo implements Comparable { + public final ServiceInfo service; + public final ComponentName componentName; + public final String key; + public final ComponentName settings; + public final CharSequence label; + public final String labelStr; + public final CharSequence appLabel; + + public BaseInfo(PackageManager pm, ServiceInfo _service, String _settings) { + service = _service; + componentName = new ComponentName(_service.packageName, _service.name); + key = componentName.flattenToShortString(); + settings = _settings != null + ? new ComponentName(_service.packageName, _settings) : null; + label = _service.loadLabel(pm); + labelStr = label.toString(); + appLabel = _service.applicationInfo.loadLabel(pm); + } + + @Override + public int compareTo(Object another) { + return labelStr.compareTo(((BaseInfo)another).labelStr); + } + } + + static public class InteractionInfo extends BaseInfo { + public final VoiceInteractionServiceInfo serviceInfo; + + public InteractionInfo(PackageManager pm, VoiceInteractionServiceInfo _service) { + super(pm, _service.getServiceInfo(), _service.getSettingsActivity()); + serviceInfo = _service; + } + } + + static public class RecognizerInfo extends BaseInfo { + public RecognizerInfo(PackageManager pm, ServiceInfo _service, String _settings) { + super(pm, _service, _settings); + } + } + + final ArrayList<InteractionInfo> mAvailableInteractionInfos = new ArrayList<>(); + final ArrayList<RecognizerInfo> mAvailableRecognizerInfos = new ArrayList<>(); + + ComponentName mCurrentVoiceInteraction; + ComponentName mCurrentRecognizer; + + public VoiceInputHelper(Context context) { + mContext = context; + + mAvailableVoiceInteractions = mContext.getPackageManager().queryIntentServices( + new Intent(VoiceInteractionService.SERVICE_INTERFACE), + PackageManager.GET_META_DATA); + mAvailableRecognition = mContext.getPackageManager().queryIntentServices( + new Intent(RecognitionService.SERVICE_INTERFACE), + PackageManager.GET_META_DATA); + } + + public boolean hasItems() { + return mAvailableVoiceInteractions.size() > 0 || mAvailableRecognition.size() > 0; + } + + public void buildUi() { + // Get the currently selected interactor from the secure setting. + String currentSetting = Settings.Secure.getString( + mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE); + if (currentSetting != null && !currentSetting.isEmpty()) { + mCurrentVoiceInteraction = ComponentName.unflattenFromString(currentSetting); + } else { + mCurrentVoiceInteraction = null; + } + + ArraySet<ComponentName> interactorRecognizers = new ArraySet<>(); + + // Iterate through all the available interactors and load up their info to show + // in the preference. + int size = mAvailableVoiceInteractions.size(); + for (int i = 0; i < size; i++) { + ResolveInfo resolveInfo = mAvailableVoiceInteractions.get(i); + VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo( + mContext.getPackageManager(), resolveInfo.serviceInfo); + if (info.getParseError() != null) { + Log.w("VoiceInteractionService", "Error in VoiceInteractionService " + + resolveInfo.serviceInfo.packageName + "/" + + resolveInfo.serviceInfo.name + ": " + info.getParseError()); + continue; + } + mAvailableInteractionInfos.add(new InteractionInfo(mContext.getPackageManager(), info)); + if (info.getRecognitionService() != null) { + interactorRecognizers.add(new ComponentName(resolveInfo.serviceInfo.packageName, + info.getRecognitionService())); + } + } + Collections.sort(mAvailableInteractionInfos); + + // Get the currently selected recognizer from the secure setting. + currentSetting = Settings.Secure.getString( + mContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE); + if (currentSetting != null && !currentSetting.isEmpty()) { + mCurrentRecognizer = ComponentName.unflattenFromString(currentSetting); + } else { + mCurrentRecognizer = null; + } + + // Iterate through all the available recognizers and load up their info to show + // in the preference. + size = mAvailableRecognition.size(); + for (int i = 0; i < size; i++) { + ResolveInfo resolveInfo = mAvailableRecognition.get(i); + ComponentName comp = new ComponentName(resolveInfo.serviceInfo.packageName, + resolveInfo.serviceInfo.name); + if (interactorRecognizers.contains(comp)) { + //continue; + } + ServiceInfo si = resolveInfo.serviceInfo; + XmlResourceParser parser = null; + String settingsActivity = null; + try { + parser = si.loadXmlMetaData(mContext.getPackageManager(), + RecognitionService.SERVICE_META_DATA); + if (parser == null) { + throw new XmlPullParserException("No " + RecognitionService.SERVICE_META_DATA + + " meta-data for " + si.packageName); + } + + Resources res = mContext.getPackageManager().getResourcesForApplication( + si.applicationInfo); + + AttributeSet attrs = Xml.asAttributeSet(parser); + + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + } + + String nodeName = parser.getName(); + if (!"recognition-service".equals(nodeName)) { + throw new XmlPullParserException( + "Meta-data does not start with recognition-service tag"); + } + + TypedArray array = res.obtainAttributes(attrs, + com.android.internal.R.styleable.RecognitionService); + settingsActivity = array.getString( + com.android.internal.R.styleable.RecognitionService_settingsActivity); + array.recycle(); + } catch (XmlPullParserException e) { + Log.e(TAG, "error parsing recognition service meta-data", e); + } catch (IOException e) { + Log.e(TAG, "error parsing recognition service meta-data", e); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "error parsing recognition service meta-data", e); + } finally { + if (parser != null) parser.close(); + } + mAvailableRecognizerInfos.add(new RecognizerInfo(mContext.getPackageManager(), + resolveInfo.serviceInfo, settingsActivity)); + } + Collections.sort(mAvailableRecognizerInfos); + } +} |