• 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.internal.app;
18 
19 import android.annotation.NonNull;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageManager;
25 import android.os.Bundle;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.os.ServiceManager;
29 import android.provider.Settings;
30 import android.util.Log;
31 
32 import java.util.ArrayList;
33 import java.util.Set;
34 
35 /**
36  * Utility method for dealing with the assistant aspects of
37  * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
38  */
39 public class AssistUtils {
40 
41     private static final String TAG = "AssistUtils";
42 
43     /** bundle key: how was the assistant invoked? */
44     public static final String INVOCATION_TYPE_KEY = "invocation_type";
45     /** value for INVOCATION_TYPE_KEY: no data */
46     public static final int INVOCATION_TYPE_UNKNOWN = 0;
47     /** value for INVOCATION_TYPE_KEY: on-screen swipe gesture */
48     public static final int INVOCATION_TYPE_GESTURE = 1;
49     /** value for INVOCATION_TYPE_KEY: device-specific physical gesture */
50     public static final int INVOCATION_TYPE_PHYSICAL_GESTURE = 2;
51     /** value for INVOCATION_TYPE_KEY: voice hotword */
52     public static final int INVOCATION_TYPE_VOICE = 3;
53     /** value for INVOCATION_TYPE_KEY: search bar affordance */
54     public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
55     /** value for INVOCATION_TYPE_KEY: long press on home navigation button */
56     public static final int INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS = 5;
57     /** value for INVOCATION_TYPE_KEY: long press on physical power button */
58     public static final int INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS = 6;
59 
60     private final Context mContext;
61     private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
62 
63     @UnsupportedAppUsage
AssistUtils(Context context)64     public AssistUtils(Context context) {
65         mContext = context;
66         mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
67                 ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
68     }
69 
showSessionForActiveService(Bundle args, int sourceFlags, IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken)70     public boolean showSessionForActiveService(Bundle args, int sourceFlags,
71             IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
72         try {
73             if (mVoiceInteractionManagerService != null) {
74                 return mVoiceInteractionManagerService.showSessionForActiveService(args,
75                         sourceFlags, showCallback, activityToken);
76             }
77         } catch (RemoteException e) {
78             Log.w(TAG, "Failed to call showSessionForActiveService", e);
79         }
80         return false;
81     }
82 
83     /**
84      * Checks the availability of a set of voice actions for the current active voice service.
85      *
86      * @param voiceActions A set of supported voice actions to be checked.
87      * @param callback     The callback which will deliver a set of supported voice actions. If
88      *                     no voice actions are supported for the given voice action set, then null
89      *                     or empty set is provided.
90      */
getActiveServiceSupportedActions(@onNull Set<String> voiceActions, @NonNull IVoiceActionCheckCallback callback)91     public void getActiveServiceSupportedActions(@NonNull Set<String> voiceActions,
92             @NonNull IVoiceActionCheckCallback callback) {
93         try {
94             if (mVoiceInteractionManagerService != null) {
95                 mVoiceInteractionManagerService
96                         .getActiveServiceSupportedActions(new ArrayList<>(voiceActions), callback);
97             }
98         } catch (RemoteException e) {
99             Log.w(TAG, "Failed to call activeServiceSupportedActions", e);
100             try {
101                 callback.onComplete(null);
102             } catch (RemoteException re) {
103             }
104         }
105     }
106 
launchVoiceAssistFromKeyguard()107     public void launchVoiceAssistFromKeyguard() {
108         try {
109             if (mVoiceInteractionManagerService != null) {
110                 mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
111             }
112         } catch (RemoteException e) {
113             Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
114         }
115     }
116 
activeServiceSupportsAssistGesture()117     public boolean activeServiceSupportsAssistGesture() {
118         try {
119             return mVoiceInteractionManagerService != null
120                     && mVoiceInteractionManagerService.activeServiceSupportsAssist();
121         } catch (RemoteException e) {
122             Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
123             return false;
124         }
125     }
126 
activeServiceSupportsLaunchFromKeyguard()127     public boolean activeServiceSupportsLaunchFromKeyguard() {
128         try {
129             return mVoiceInteractionManagerService != null
130                     && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
131         } catch (RemoteException e) {
132             Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
133             return false;
134         }
135     }
136 
getActiveServiceComponentName()137     public ComponentName getActiveServiceComponentName() {
138         try {
139             if (mVoiceInteractionManagerService != null) {
140                 return mVoiceInteractionManagerService.getActiveServiceComponentName();
141             } else {
142                 return null;
143             }
144         } catch (RemoteException e) {
145             Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
146             return null;
147         }
148     }
149 
isSessionRunning()150     public boolean isSessionRunning() {
151         try {
152             return mVoiceInteractionManagerService != null
153                     && mVoiceInteractionManagerService.isSessionRunning();
154         } catch (RemoteException e) {
155             Log.w(TAG, "Failed to call isSessionRunning", e);
156             return false;
157         }
158     }
159 
hideCurrentSession()160     public void hideCurrentSession() {
161         try {
162             if (mVoiceInteractionManagerService != null) {
163                 mVoiceInteractionManagerService.hideCurrentSession();
164             }
165         } catch (RemoteException e) {
166             Log.w(TAG, "Failed to call hideCurrentSession", e);
167         }
168     }
169 
onLockscreenShown()170     public void onLockscreenShown() {
171         try {
172             if (mVoiceInteractionManagerService != null) {
173                 mVoiceInteractionManagerService.onLockscreenShown();
174             }
175         } catch (RemoteException e) {
176             Log.w(TAG, "Failed to call onLockscreenShown", e);
177         }
178     }
179 
registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener)180     public void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener) {
181         try {
182             if (mVoiceInteractionManagerService != null) {
183                 mVoiceInteractionManagerService.registerVoiceInteractionSessionListener(listener);
184             }
185         } catch (RemoteException e) {
186             Log.w(TAG, "Failed to register voice interaction listener", e);
187         }
188     }
189 
190     @UnsupportedAppUsage
getAssistComponentForUser(int userId)191     public ComponentName getAssistComponentForUser(int userId) {
192         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
193                 Settings.Secure.ASSISTANT, userId);
194         if (setting != null) {
195             return ComponentName.unflattenFromString(setting);
196         } else {
197             return null;
198         }
199     }
200 
isPreinstalledAssistant(Context context, ComponentName assistant)201     public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
202         if (assistant == null) {
203             return false;
204         }
205         ApplicationInfo applicationInfo;
206         try {
207             applicationInfo = context.getPackageManager().getApplicationInfo(
208                     assistant.getPackageName(), 0);
209         } catch (PackageManager.NameNotFoundException e) {
210             return false;
211         }
212         return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
213     }
214 
isDisclosureEnabled(Context context)215     public static boolean isDisclosureEnabled(Context context) {
216         return Settings.Secure.getInt(context.getContentResolver(),
217                 Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
218     }
219 
220     /**
221      * @return if the disclosure animation should trigger for the given assistant.
222      *
223      * Third-party assistants will always need to disclose, while the user can configure this for
224      * pre-installed assistants.
225      */
shouldDisclose(Context context, ComponentName assistant)226     public static boolean shouldDisclose(Context context, ComponentName assistant) {
227         if (!allowDisablingAssistDisclosure(context)) {
228             return true;
229         }
230 
231         return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
232     }
233 
allowDisablingAssistDisclosure(Context context)234     public static boolean allowDisablingAssistDisclosure(Context context) {
235         return context.getResources().getBoolean(
236                 com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
237     }
238 }
239