Home | History | Annotate | Download | only in voice
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.settings.voice;
     18 
     19 import android.content.ComponentName;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.pm.PackageManager;
     23 import android.content.pm.ResolveInfo;
     24 import android.content.pm.ServiceInfo;
     25 import android.preference.Preference;
     26 import android.provider.Settings;
     27 import android.service.voice.VoiceInteractionService;
     28 import android.service.voice.VoiceInteractionServiceInfo;
     29 import android.speech.RecognitionService;
     30 import com.android.settings.R;
     31 import com.android.settings.SettingsPreferenceFragment;
     32 import com.android.settings.search.BaseSearchIndexProvider;
     33 import com.android.settings.search.Indexable;
     34 import com.android.settings.search.SearchIndexableRaw;
     35 import com.android.settings.voice.VoiceInputPreference.RadioButtonGroupState;
     36 
     37 import android.os.Bundle;
     38 import android.preference.PreferenceCategory;
     39 import android.widget.Checkable;
     40 
     41 import java.util.ArrayList;
     42 import java.util.List;
     43 
     44 public class VoiceInputSettings extends SettingsPreferenceFragment implements
     45         Preference.OnPreferenceClickListener, RadioButtonGroupState, Indexable {
     46 
     47     private static final String TAG = "VoiceInputSettings";
     48     private static final boolean DBG = false;
     49 
     50     /**
     51      * Preference key for the engine selection preference.
     52      */
     53     private static final String KEY_SERVICE_PREFERENCE_SECTION =
     54             "voice_service_preference_section";
     55 
     56     private PreferenceCategory mServicePreferenceCategory;
     57 
     58     private CharSequence mInteractorSummary;
     59     private CharSequence mRecognizerSummary;
     60     private CharSequence mInteractorWarning;
     61 
     62     /**
     63      * The currently selected engine.
     64      */
     65     private String mCurrentKey;
     66 
     67     /**
     68      * The engine checkbox that is currently checked. Saves us a bit of effort
     69      * in deducing the right one from the currently selected engine.
     70      */
     71     private Checkable mCurrentChecked;
     72 
     73     private VoiceInputHelper mHelper;
     74 
     75     @Override
     76     public void onCreate(Bundle savedInstanceState) {
     77         super.onCreate(savedInstanceState);
     78         addPreferencesFromResource(R.xml.voice_input_settings);
     79 
     80         mServicePreferenceCategory = (PreferenceCategory) findPreference(
     81                 KEY_SERVICE_PREFERENCE_SECTION);
     82 
     83         mInteractorSummary = getActivity().getText(
     84                 R.string.voice_interactor_preference_summary);
     85         mRecognizerSummary = getActivity().getText(
     86                 R.string.voice_recognizer_preference_summary);
     87         mInteractorWarning = getActivity().getText(R.string.voice_interaction_security_warning);
     88     }
     89 
     90     @Override
     91     public void onStart() {
     92         super.onStart();
     93         initSettings();
     94     }
     95 
     96     private void initSettings() {
     97         mHelper = new VoiceInputHelper(getActivity());
     98         mHelper.buildUi();
     99 
    100         mServicePreferenceCategory.removeAll();
    101 
    102         if (mHelper.mCurrentVoiceInteraction != null) {
    103             mCurrentKey = mHelper.mCurrentVoiceInteraction.flattenToShortString();
    104         } else if (mHelper.mCurrentRecognizer != null) {
    105             mCurrentKey = mHelper.mCurrentRecognizer.flattenToShortString();
    106         } else {
    107             mCurrentKey = null;
    108         }
    109 
    110         for (int i=0; i<mHelper.mAvailableInteractionInfos.size(); i++) {
    111             VoiceInputHelper.InteractionInfo info = mHelper.mAvailableInteractionInfos.get(i);
    112             VoiceInputPreference pref = new VoiceInputPreference(getActivity(), info,
    113                     mInteractorSummary, mInteractorWarning, this);
    114             mServicePreferenceCategory.addPreference(pref);
    115         }
    116 
    117         for (int i=0; i<mHelper.mAvailableRecognizerInfos.size(); i++) {
    118             VoiceInputHelper.RecognizerInfo info = mHelper.mAvailableRecognizerInfos.get(i);
    119             VoiceInputPreference pref = new VoiceInputPreference(getActivity(), info,
    120                     mRecognizerSummary, null, this);
    121             mServicePreferenceCategory.addPreference(pref);
    122         }
    123     }
    124 
    125     @Override
    126     public Checkable getCurrentChecked() {
    127         return mCurrentChecked;
    128     }
    129 
    130     @Override
    131     public String getCurrentKey() {
    132         return mCurrentKey;
    133     }
    134 
    135     @Override
    136     public void setCurrentChecked(Checkable current) {
    137         mCurrentChecked = current;
    138     }
    139 
    140     @Override
    141     public void setCurrentKey(String key) {
    142         mCurrentKey = key;
    143         for (int i=0; i<mHelper.mAvailableInteractionInfos.size(); i++) {
    144             VoiceInputHelper.InteractionInfo info = mHelper.mAvailableInteractionInfos.get(i);
    145             if (info.key.equals(key)) {
    146                 // Put the new value back into secure settings.
    147                 Settings.Secure.putString(getActivity().getContentResolver(),
    148                         Settings.Secure.VOICE_INTERACTION_SERVICE, key);
    149                 // Eventually we will require that an interactor always specify a recognizer
    150                 if (info.settings != null) {
    151                     Settings.Secure.putString(getActivity().getContentResolver(),
    152                             Settings.Secure.VOICE_RECOGNITION_SERVICE,
    153                             info.settings.flattenToShortString());
    154                 }
    155                 return;
    156             }
    157         }
    158 
    159         for (int i=0; i<mHelper.mAvailableRecognizerInfos.size(); i++) {
    160             VoiceInputHelper.RecognizerInfo info = mHelper.mAvailableRecognizerInfos.get(i);
    161             if (info.key.equals(key)) {
    162                 Settings.Secure.putString(getActivity().getContentResolver(),
    163                         Settings.Secure.VOICE_INTERACTION_SERVICE, "");
    164                 Settings.Secure.putString(getActivity().getContentResolver(),
    165                         Settings.Secure.VOICE_RECOGNITION_SERVICE, key);
    166                 return;
    167             }
    168         }
    169     }
    170 
    171     @Override
    172     public boolean onPreferenceClick(Preference preference) {
    173         if (preference instanceof VoiceInputPreference) {
    174             ((VoiceInputPreference)preference).doClick();
    175         }
    176         return true;
    177     }
    178 
    179     // For Search
    180     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    181         new BaseSearchIndexProvider() {
    182 
    183             @Override
    184             public List<SearchIndexableRaw> getRawDataToIndex(Context context,
    185                     boolean enabled) {
    186 
    187                 List<SearchIndexableRaw> indexables = new ArrayList<>();
    188 
    189                 final String screenTitle = context.getString(R.string.voice_input_settings_title);
    190 
    191                 SearchIndexableRaw indexable = new SearchIndexableRaw(context);
    192                 indexable.key = "voice_service_preference_section_title";
    193                 indexable.title = context.getString(R.string.voice_service_preference_section_title);
    194                 indexable.screenTitle = screenTitle;
    195                 indexables.add(indexable);
    196 
    197                 final List<ResolveInfo> voiceInteractions =
    198                         context.getPackageManager().queryIntentServices(
    199                                 new Intent(VoiceInteractionService.SERVICE_INTERFACE),
    200                                 PackageManager.GET_META_DATA);
    201 
    202                 final int countInteractions = voiceInteractions.size();
    203                 for (int i = 0; i < countInteractions; i++) {
    204                     ResolveInfo info = voiceInteractions.get(i);
    205                     VoiceInteractionServiceInfo visInfo = new VoiceInteractionServiceInfo(
    206                             context.getPackageManager(), info.serviceInfo);
    207                     if (visInfo.getParseError() != null) {
    208                         continue;
    209                     }
    210                     indexables.add(getSearchIndexableRaw(context, info, screenTitle));
    211                 }
    212 
    213                 final List<ResolveInfo> recognitions =
    214                         context.getPackageManager().queryIntentServices(
    215                                 new Intent(RecognitionService.SERVICE_INTERFACE),
    216                                 PackageManager.GET_META_DATA);
    217 
    218                 final int countRecognitions = recognitions.size();
    219                 for (int i = 0; i < countRecognitions; i++) {
    220                     ResolveInfo info = recognitions.get(i);
    221                     indexables.add(getSearchIndexableRaw(context, info, screenTitle));
    222                 }
    223 
    224                 return indexables;
    225             }
    226 
    227             private SearchIndexableRaw getSearchIndexableRaw(Context context,
    228                     ResolveInfo info, String screenTitle) {
    229 
    230                 ServiceInfo serviceInfo = info.serviceInfo;
    231                 ComponentName componentName = new ComponentName(serviceInfo.packageName,
    232                         serviceInfo.name);
    233 
    234                 SearchIndexableRaw indexable = new SearchIndexableRaw(context);
    235                 indexable.key = componentName.flattenToString();
    236                 indexable.title = info.loadLabel(context.getPackageManager()).toString();
    237                 indexable.screenTitle = screenTitle;
    238 
    239                 return indexable;
    240             }
    241         };
    242 }
    243