blob: 9ae614982fb55484db14a952dd5daa431b706ce1 [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
Andrei Oneaeecddd52019-03-27 10:32:55 +000021import android.annotation.UnsupportedAppUsage;
Adrian Roose9175082015-06-15 13:23:14 -070022import android.app.SearchManager;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.Intent;
Adrian Roos2335bd62016-08-11 15:42:40 -070026import android.content.pm.ApplicationInfo;
Jorim Jaggi165ce062015-07-06 16:18:11 -070027import android.content.pm.PackageManager;
28import android.content.pm.ResolveInfo;
29import android.os.Bundle;
Dianne Hackborn17f69352015-07-17 18:04:14 -070030import android.os.IBinder;
Adrian Roose9175082015-06-15 13:23:14 -070031import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.provider.Settings;
34import android.util.Log;
35
Dan Sandler7105e372018-10-19 18:12:40 -040036import com.android.internal.R;
37
Adrian Roose9175082015-06-15 13:23:14 -070038/**
39 * Utility method for dealing with the assistant aspects of
40 * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
41 */
42public class AssistUtils {
43
44 private static final String TAG = "AssistUtils";
45
Dan Sandler7105e372018-10-19 18:12:40 -040046 /**
47 * Sentinel value for "no default assistant specified."
48 *
49 * Empty string is already used to represent an explicit setting of No Assistant. null cannot
50 * be used because we can't represent a null value in XML.
51 */
52 private static final String UNSET = "#+UNSET";
53
Adrian Roose9175082015-06-15 13:23:14 -070054 private final Context mContext;
55 private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
56
Andrei Oneaeecddd52019-03-27 10:32:55 +000057 @UnsupportedAppUsage
Adrian Roose9175082015-06-15 13:23:14 -070058 public AssistUtils(Context context) {
59 mContext = context;
60 mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
61 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
62 }
63
Dianne Hackborn17f69352015-07-17 18:04:14 -070064 public boolean showSessionForActiveService(Bundle args, int sourceFlags,
65 IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
Adrian Roose9175082015-06-15 13:23:14 -070066 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -070067 if (mVoiceInteractionManagerService != null) {
68 return mVoiceInteractionManagerService.showSessionForActiveService(args,
69 sourceFlags, showCallback, activityToken);
70 }
Adrian Roose9175082015-06-15 13:23:14 -070071 } catch (RemoteException e) {
72 Log.w(TAG, "Failed to call showSessionForActiveService", e);
73 }
Dianne Hackborn17f69352015-07-17 18:04:14 -070074 return false;
Adrian Roose9175082015-06-15 13:23:14 -070075 }
76
77 public void launchVoiceAssistFromKeyguard() {
78 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -070079 if (mVoiceInteractionManagerService != null) {
80 mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
81 }
Adrian Roose9175082015-06-15 13:23:14 -070082 } catch (RemoteException e) {
83 Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
84 }
85 }
86
87 public boolean activeServiceSupportsAssistGesture() {
88 try {
89 return mVoiceInteractionManagerService != null
90 && mVoiceInteractionManagerService.activeServiceSupportsAssist();
91 } catch (RemoteException e) {
92 Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
93 return false;
94 }
95 }
96
97 public boolean activeServiceSupportsLaunchFromKeyguard() {
98 try {
99 return mVoiceInteractionManagerService != null
100 && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
101 } catch (RemoteException e) {
102 Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
103 return false;
104 }
105 }
106
107 public ComponentName getActiveServiceComponentName() {
108 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -0700109 if (mVoiceInteractionManagerService != null) {
110 return mVoiceInteractionManagerService.getActiveServiceComponentName();
111 } else {
112 return null;
113 }
Adrian Roose9175082015-06-15 13:23:14 -0700114 } catch (RemoteException e) {
115 Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
116 return null;
117 }
118 }
119
120 public boolean isSessionRunning() {
121 try {
122 return mVoiceInteractionManagerService != null
123 && mVoiceInteractionManagerService.isSessionRunning();
124 } catch (RemoteException e) {
125 Log.w(TAG, "Failed to call isSessionRunning", e);
126 return false;
127 }
128 }
129
130 public void hideCurrentSession() {
131 try {
Jorim Jaggie446dce2015-07-20 14:44:55 -0700132 if (mVoiceInteractionManagerService != null) {
133 mVoiceInteractionManagerService.hideCurrentSession();
134 }
Adrian Roose9175082015-06-15 13:23:14 -0700135 } catch (RemoteException e) {
136 Log.w(TAG, "Failed to call hideCurrentSession", e);
137 }
138 }
139
Jorim Jaggi19695d92015-07-20 15:51:40 -0700140 public void onLockscreenShown() {
141 try {
142 if (mVoiceInteractionManagerService != null) {
143 mVoiceInteractionManagerService.onLockscreenShown();
144 }
145 } catch (RemoteException e) {
146 Log.w(TAG, "Failed to call onLockscreenShown", e);
147 }
148 }
149
Annie Chinecb9f3e2016-06-27 16:01:52 -0700150 public void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener) {
151 try {
152 if (mVoiceInteractionManagerService != null) {
153 mVoiceInteractionManagerService.registerVoiceInteractionSessionListener(listener);
154 }
155 } catch (RemoteException e) {
156 Log.w(TAG, "Failed to register voice interaction listener", e);
157 }
158 }
159
Andrei Oneaeecddd52019-03-27 10:32:55 +0000160 @UnsupportedAppUsage
Adrian Roose9175082015-06-15 13:23:14 -0700161 public ComponentName getAssistComponentForUser(int userId) {
162 final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
163 Settings.Secure.ASSISTANT, userId);
164 if (setting != null) {
165 return ComponentName.unflattenFromString(setting);
166 }
167
Dan Sandler7105e372018-10-19 18:12:40 -0400168 final String defaultSetting = mContext.getResources().getString(
169 R.string.config_defaultAssistantComponentName);
170 if (defaultSetting != null && !defaultSetting.equals(UNSET)) {
171 return ComponentName.unflattenFromString(defaultSetting);
172 }
173
Adrian Roose9175082015-06-15 13:23:14 -0700174 // Fallback to keep backward compatible behavior when there is no user setting.
175 if (activeServiceSupportsAssistGesture()) {
176 return getActiveServiceComponentName();
177 }
Dan Sandler7105e372018-10-19 18:12:40 -0400178
179 if (UNSET.equals(defaultSetting)) {
180 return null;
181 }
182
Steven Wu3aa2cf72018-05-25 15:20:10 -0400183 final SearchManager searchManager =
184 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
185 if (searchManager == null) {
186 return null;
187 }
188 final Intent intent = searchManager.getAssistIntent(false);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700189 PackageManager pm = mContext.getPackageManager();
190 ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
191 userId);
192 if (info != null) {
193 return new ComponentName(info.activityInfo.applicationInfo.packageName,
194 info.activityInfo.name);
Adrian Roose9175082015-06-15 13:23:14 -0700195 }
Adrian Roose9175082015-06-15 13:23:14 -0700196 return null;
197 }
198
Adrian Roos2335bd62016-08-11 15:42:40 -0700199 public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
200 if (assistant == null) {
201 return false;
202 }
203 ApplicationInfo applicationInfo;
204 try {
205 applicationInfo = context.getPackageManager().getApplicationInfo(
206 assistant.getPackageName(), 0);
207 } catch (PackageManager.NameNotFoundException e) {
208 return false;
209 }
210 return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
211 }
212
213 private static boolean isDisclosureEnabled(Context context) {
214 return Settings.Secure.getInt(context.getContentResolver(),
215 Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
216 }
217
218 /**
219 * @return if the disclosure animation should trigger for the given assistant.
220 *
221 * Third-party assistants will always need to disclose, while the user can configure this for
222 * pre-installed assistants.
223 */
224 public static boolean shouldDisclose(Context context, ComponentName assistant) {
225 if (!allowDisablingAssistDisclosure(context)) {
226 return true;
227 }
228
229 return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
230 }
231
232 public static boolean allowDisablingAssistDisclosure(Context context) {
233 return context.getResources().getBoolean(
234 com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
235 }
Adrian Roose9175082015-06-15 13:23:14 -0700236}