blob: fed0a89a4d75fce1ac9d3f323483a8cfd055fe30 [file] [log] [blame]
Adrian Roose9175082015-06-15 13:23:14 -07001/*
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
17package com.android.internal.app;
18
Adrian Roos2335bd62016-08-11 15:42:40 -070019import com.android.internal.R;
20
Adrian Roose9175082015-06-15 13:23:14 -070021import android.app.SearchManager;
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.Intent;
Adrian Roos2335bd62016-08-11 15:42:40 -070025import android.content.pm.ApplicationInfo;
Jorim Jaggi165ce062015-07-06 16:18:11 -070026import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
28import android.os.Bundle;
Dianne Hackborn17f69352015-07-17 18:04:14 -070029import android.os.IBinder;
Adrian Roose9175082015-06-15 13:23:14 -070030import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.provider.Settings;
33import android.util.Log;
34
Dan Sandler7105e372018-10-19 18:12:40 -040035import com.android.internal.R;
36
Adrian Roose9175082015-06-15 13:23:14 -070037/**
38 * Utility method for dealing with the assistant aspects of
39 * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
40 */
41public class AssistUtils {
42
43 private static final String TAG = "AssistUtils";
44
Dan Sandler7105e372018-10-19 18:12:40 -040045 /**
46 * Sentinel value for "no default assistant specified."
47 *
48 * Empty string is already used to represent an explicit setting of No Assistant. null cannot
49 * be used because we can't represent a null value in XML.
50 */
51 private static final String UNSET = "#+UNSET";
52
Adrian Roose9175082015-06-15 13:23:14 -070053 private final Context mContext;
54 private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
55
56 public AssistUtils(Context context) {
57 mContext = context;
58 mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
59 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
60 }
61
Dianne Hackborn17f69352015-07-17 18:04:14 -070062 public boolean showSessionForActiveService(Bundle args, int sourceFlags,
63 IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
Adrian Roose9175082015-06-15 13:23:14 -070064 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -070065 if (mVoiceInteractionManagerService != null) {
66 return mVoiceInteractionManagerService.showSessionForActiveService(args,
67 sourceFlags, showCallback, activityToken);
68 }
Adrian Roose9175082015-06-15 13:23:14 -070069 } catch (RemoteException e) {
70 Log.w(TAG, "Failed to call showSessionForActiveService", e);
71 }
Dianne Hackborn17f69352015-07-17 18:04:14 -070072 return false;
Adrian Roose9175082015-06-15 13:23:14 -070073 }
74
75 public void launchVoiceAssistFromKeyguard() {
76 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -070077 if (mVoiceInteractionManagerService != null) {
78 mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
79 }
Adrian Roose9175082015-06-15 13:23:14 -070080 } catch (RemoteException e) {
81 Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
82 }
83 }
84
85 public boolean activeServiceSupportsAssistGesture() {
86 try {
87 return mVoiceInteractionManagerService != null
88 && mVoiceInteractionManagerService.activeServiceSupportsAssist();
89 } catch (RemoteException e) {
90 Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
91 return false;
92 }
93 }
94
95 public boolean activeServiceSupportsLaunchFromKeyguard() {
96 try {
97 return mVoiceInteractionManagerService != null
98 && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
99 } catch (RemoteException e) {
100 Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
101 return false;
102 }
103 }
104
105 public ComponentName getActiveServiceComponentName() {
106 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -0700107 if (mVoiceInteractionManagerService != null) {
108 return mVoiceInteractionManagerService.getActiveServiceComponentName();
109 } else {
110 return null;
111 }
Adrian Roose9175082015-06-15 13:23:14 -0700112 } catch (RemoteException e) {
113 Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
114 return null;
115 }
116 }
117
118 public boolean isSessionRunning() {
119 try {
120 return mVoiceInteractionManagerService != null
121 && mVoiceInteractionManagerService.isSessionRunning();
122 } catch (RemoteException e) {
123 Log.w(TAG, "Failed to call isSessionRunning", e);
124 return false;
125 }
126 }
127
128 public void hideCurrentSession() {
129 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -0700130 if (mVoiceInteractionManagerService != null) {
131 mVoiceInteractionManagerService.hideCurrentSession();
132 }
Adrian Roose9175082015-06-15 13:23:14 -0700133 } catch (RemoteException e) {
134 Log.w(TAG, "Failed to call hideCurrentSession", e);
135 }
136 }
137
Jorim Jaggi19695d92015-07-20 15:51:40 -0700138 public void onLockscreenShown() {
139 try {
140 if (mVoiceInteractionManagerService != null) {
141 mVoiceInteractionManagerService.onLockscreenShown();
142 }
143 } catch (RemoteException e) {
144 Log.w(TAG, "Failed to call onLockscreenShown", e);
145 }
146 }
147
Annie Chinecb9f3e2016-06-27 16:01:52 -0700148 public void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener) {
149 try {
150 if (mVoiceInteractionManagerService != null) {
151 mVoiceInteractionManagerService.registerVoiceInteractionSessionListener(listener);
152 }
153 } catch (RemoteException e) {
154 Log.w(TAG, "Failed to register voice interaction listener", e);
155 }
156 }
157
Adrian Roose9175082015-06-15 13:23:14 -0700158 public ComponentName getAssistComponentForUser(int userId) {
159 final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
160 Settings.Secure.ASSISTANT, userId);
161 if (setting != null) {
162 return ComponentName.unflattenFromString(setting);
163 }
164
Dan Sandler7105e372018-10-19 18:12:40 -0400165 final String defaultSetting = mContext.getResources().getString(
166 R.string.config_defaultAssistantComponentName);
167 if (defaultSetting != null && !defaultSetting.equals(UNSET)) {
168 return ComponentName.unflattenFromString(defaultSetting);
169 }
170
Adrian Roose9175082015-06-15 13:23:14 -0700171 // Fallback to keep backward compatible behavior when there is no user setting.
172 if (activeServiceSupportsAssistGesture()) {
173 return getActiveServiceComponentName();
174 }
Dan Sandler7105e372018-10-19 18:12:40 -0400175
176 if (UNSET.equals(defaultSetting)) {
177 return null;
178 }
179
Steven Wu3aa2cf72018-05-25 15:20:10 -0400180 final SearchManager searchManager =
181 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
182 if (searchManager == null) {
183 return null;
184 }
185 final Intent intent = searchManager.getAssistIntent(false);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700186 PackageManager pm = mContext.getPackageManager();
187 ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
188 userId);
189 if (info != null) {
190 return new ComponentName(info.activityInfo.applicationInfo.packageName,
191 info.activityInfo.name);
Adrian Roose9175082015-06-15 13:23:14 -0700192 }
Adrian Roose9175082015-06-15 13:23:14 -0700193 return null;
194 }
195
Adrian Roos2335bd62016-08-11 15:42:40 -0700196 public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
197 if (assistant == null) {
198 return false;
199 }
200 ApplicationInfo applicationInfo;
201 try {
202 applicationInfo = context.getPackageManager().getApplicationInfo(
203 assistant.getPackageName(), 0);
204 } catch (PackageManager.NameNotFoundException e) {
205 return false;
206 }
207 return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
208 }
209
210 private static boolean isDisclosureEnabled(Context context) {
211 return Settings.Secure.getInt(context.getContentResolver(),
212 Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
213 }
214
215 /**
216 * @return if the disclosure animation should trigger for the given assistant.
217 *
218 * Third-party assistants will always need to disclose, while the user can configure this for
219 * pre-installed assistants.
220 */
221 public static boolean shouldDisclose(Context context, ComponentName assistant) {
222 if (!allowDisablingAssistDisclosure(context)) {
223 return true;
224 }
225
226 return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
227 }
228
229 public static boolean allowDisablingAssistDisclosure(Context context) {
230 return context.getResources().getBoolean(
231 com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
232 }
Adrian Roose9175082015-06-15 13:23:14 -0700233}