• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.applications;
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.os.UserHandle;
25 import android.provider.Settings;
26 import android.service.voice.VoiceInteractionService;
27 import android.service.voice.VoiceInteractionServiceInfo;
28 import android.speech.RecognitionService;
29 import android.util.AttributeSet;
30 import android.util.Log;
31 
32 import com.android.internal.app.AssistUtils;
33 import com.android.settings.AppListPreferenceWithSettings;
34 import com.android.settings.R;
35 
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 public class DefaultAssistPreference extends AppListPreferenceWithSettings {
40 
41     private static final String TAG = DefaultAssistPreference.class.getSimpleName();
42 
43     private final List<Info> mAvailableAssistants = new ArrayList<>();
44 
45     private final AssistUtils mAssistUtils;
46 
DefaultAssistPreference(Context context, AttributeSet attrs)47     public DefaultAssistPreference(Context context, AttributeSet attrs) {
48         super(context, attrs);
49         setShowItemNone(true);
50         setDialogTitle(R.string.choose_assist_title);
51         mAssistUtils = new AssistUtils(context);
52     }
53 
54     @Override
persistString(String value)55     protected boolean persistString(String value) {
56         final Info info = findAssistantByPackageName(value);
57         if (info == null) {
58             setAssistNone();
59             return true;
60         }
61 
62         if (info.isVoiceInteractionService()) {
63             setAssistService(info);
64         } else {
65             setAssistActivity(info);
66         }
67         return true;
68     }
69 
setAssistNone()70     private void setAssistNone() {
71         Settings.Secure.putString(getContext().getContentResolver(),
72                 Settings.Secure.ASSISTANT, ITEM_NONE_VALUE);
73         Settings.Secure.putString(getContext().getContentResolver(),
74                 Settings.Secure.VOICE_INTERACTION_SERVICE, "");
75         Settings.Secure.putString(getContext().getContentResolver(),
76                 Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer());
77 
78         setSummary(getContext().getText(R.string.default_assist_none));
79         setSettingsComponent(null);
80     }
81 
setAssistService(Info serviceInfo)82     private void setAssistService(Info serviceInfo) {
83         final String serviceComponentName = serviceInfo.component.flattenToShortString();
84         final String serviceRecognizerName = new ComponentName(
85                 serviceInfo.component.getPackageName(),
86                 serviceInfo.voiceInteractionServiceInfo.getRecognitionService())
87                 .flattenToShortString();
88 
89         Settings.Secure.putString(getContext().getContentResolver(),
90                 Settings.Secure.ASSISTANT, serviceComponentName);
91         Settings.Secure.putString(getContext().getContentResolver(),
92                 Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName);
93         Settings.Secure.putString(getContext().getContentResolver(),
94                 Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName);
95 
96         setSummary(getEntry());
97         final String settingsActivity =
98                 serviceInfo.voiceInteractionServiceInfo.getSettingsActivity();
99         setSettingsComponent(settingsActivity == null ?
100                 null :
101                 new ComponentName(serviceInfo.component.getPackageName(), settingsActivity));
102     }
103 
setAssistActivity(Info activityInfo)104     private void setAssistActivity(Info activityInfo) {
105         Settings.Secure.putString(getContext().getContentResolver(),
106                 Settings.Secure.ASSISTANT, activityInfo.component.flattenToShortString());
107         Settings.Secure.putString(getContext().getContentResolver(),
108                 Settings.Secure.VOICE_INTERACTION_SERVICE, "");
109         Settings.Secure.putString(getContext().getContentResolver(),
110                 Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer());
111 
112         setSummary(getEntry());
113         setSettingsComponent(null);
114     }
115 
getDefaultRecognizer()116     private String getDefaultRecognizer() {
117         ResolveInfo resolveInfo = getContext().getPackageManager().resolveService(
118                 new Intent(RecognitionService.SERVICE_INTERFACE),
119                 PackageManager.GET_META_DATA);
120         if (resolveInfo == null || resolveInfo.serviceInfo == null) {
121             Log.w(TAG, "Unable to resolve default voice recognition service.");
122             return "";
123         }
124 
125         return new ComponentName(resolveInfo.serviceInfo.packageName,
126                 resolveInfo.serviceInfo.name).flattenToShortString();
127     }
128 
findAssistantByPackageName(String packageName)129     private Info findAssistantByPackageName(String packageName) {
130         for (int i = 0; i < mAvailableAssistants.size(); ++i) {
131             Info info = mAvailableAssistants.get(i);
132             if (info.component.getPackageName().equals(packageName)) {
133                 return info;
134             }
135         }
136         return null;
137     }
138 
addAssistServices()139     private void addAssistServices() {
140         PackageManager pm = getContext().getPackageManager();
141 
142         List<ResolveInfo> services = pm.queryIntentServices(
143                 new Intent(VoiceInteractionService.SERVICE_INTERFACE),
144                 PackageManager.GET_META_DATA);
145         for (int i = 0; i < services.size(); ++i) {
146             ResolveInfo resolveInfo = services.get(i);
147             VoiceInteractionServiceInfo voiceInteractionServiceInfo =
148                     new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo);
149             if (!voiceInteractionServiceInfo.getSupportsAssist()) {
150                 continue;
151             }
152 
153             mAvailableAssistants.add(new Info(
154                     new ComponentName(resolveInfo.serviceInfo.packageName,
155                                       resolveInfo.serviceInfo.name),
156                     voiceInteractionServiceInfo));
157         }
158     }
159 
addAssistActivities()160     private void addAssistActivities() {
161         PackageManager pm = getContext().getPackageManager();
162 
163         List<ResolveInfo> activities = pm.queryIntentActivities(
164                 new Intent(Intent.ACTION_ASSIST),
165                 PackageManager.MATCH_DEFAULT_ONLY);
166         for (int i = 0; i < activities.size(); ++i) {
167             ResolveInfo resolveInfo = activities.get(i);
168             mAvailableAssistants.add(new Info(
169                     new ComponentName(resolveInfo.activityInfo.packageName,
170                                       resolveInfo.activityInfo.name)));
171         }
172     }
173 
getCurrentAssist()174     public ComponentName getCurrentAssist() {
175         return mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
176     }
177 
refreshAssistApps()178     public void refreshAssistApps() {
179         mAvailableAssistants.clear();
180         addAssistServices();
181         addAssistActivities();
182 
183         List<String> packages = new ArrayList<>();
184         for (int i = 0; i < mAvailableAssistants.size(); ++i) {
185             String packageName = mAvailableAssistants.get(i).component.getPackageName();
186             if (packages.contains(packageName)) {
187                 // A service appears before an activity thus overrides it if from the same package.
188                 continue;
189             }
190             packages.add(packageName);
191         }
192 
193         ComponentName currentAssist = getCurrentAssist();
194         setPackageNames(packages.toArray(new String[packages.size()]),
195                 currentAssist == null ? null : currentAssist.getPackageName());
196     }
197 
198     private static class Info {
199         public final ComponentName component;
200         public final VoiceInteractionServiceInfo voiceInteractionServiceInfo;
201 
Info(ComponentName component)202         Info(ComponentName component) {
203             this.component = component;
204             this.voiceInteractionServiceInfo = null;
205         }
206 
Info(ComponentName component, VoiceInteractionServiceInfo voiceInteractionServiceInfo)207         Info(ComponentName component, VoiceInteractionServiceInfo voiceInteractionServiceInfo) {
208             this.component = component;
209             this.voiceInteractionServiceInfo = voiceInteractionServiceInfo;
210         }
211 
isVoiceInteractionService()212         public boolean isVoiceInteractionService() {
213             return voiceInteractionServiceInfo != null;
214         }
215     }
216 }
217