blob: 256c5d51c42155cb4dcb5ca34b94f39bd96d49b6 [file] [log] [blame]
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001package com.android.systemui.assist;
2
Lucas Dupin8968f6a2019-08-09 17:41:15 -07003import static com.android.systemui.DejankUtils.whitelistIpcs;
4
Yohei Yukawa528e4682015-09-10 22:21:04 -07005import android.annotation.NonNull;
6import android.annotation.Nullable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07007import android.app.ActivityManager;
8import android.app.ActivityOptions;
9import android.app.SearchManager;
10import android.content.ActivityNotFoundException;
11import android.content.ComponentName;
12import android.content.Context;
13import android.content.Intent;
Jason Monk9c7844c2017-01-18 15:21:53 -050014import android.content.pm.ActivityInfo;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070015import android.content.pm.PackageManager;
Jason Monk9c7844c2017-01-18 15:21:53 -050016import android.content.res.Configuration;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070017import android.content.res.Resources;
18import android.graphics.PixelFormat;
Steven Wu11da5742019-04-25 16:12:06 -040019import android.metrics.LogMaker;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070020import android.os.AsyncTask;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080021import android.os.Binder;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070022import android.os.Bundle;
Xiyuan Xiae6de8b92015-06-06 22:18:05 -070023import android.os.Handler;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070024import android.os.RemoteException;
Govinda Wasserman27aa92b2019-04-16 14:45:54 -040025import android.os.SystemClock;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070026import android.os.UserHandle;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070027import android.provider.Settings;
Dianne Hackborn17f69352015-07-17 18:04:14 -070028import android.service.voice.VoiceInteractionSession;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070029import android.util.Log;
30import android.view.Gravity;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34import android.view.WindowManager;
35import android.widget.ImageView;
36
Adrian Roose9175082015-06-15 13:23:14 -070037import com.android.internal.app.AssistUtils;
Annie Chinecb9f3e2016-06-27 16:01:52 -070038import com.android.internal.app.IVoiceInteractionSessionListener;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070039import com.android.internal.app.IVoiceInteractionSessionShowCallback;
Steven Wu11da5742019-04-25 16:12:06 -040040import com.android.internal.logging.MetricsLogger;
41import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Kaori Katou70554e02016-08-04 17:11:07 +090042import com.android.keyguard.KeyguardUpdateMonitor;
Jason Monk9c7844c2017-01-18 15:21:53 -050043import com.android.settingslib.applications.InterestingConfigChanges;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070044import com.android.systemui.R;
Miranda Kephart433c8112019-05-22 12:25:51 -040045import com.android.systemui.assist.ui.DefaultUiController;
46import com.android.systemui.recents.OverviewProxyService;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070047import com.android.systemui.statusbar.CommandQueue;
Dave Mankoffbba732d2019-11-20 13:04:54 -050048import com.android.systemui.statusbar.policy.ConfigurationController;
Jason Monk9c7844c2017-01-18 15:21:53 -050049import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Adrian Roose9175082015-06-15 13:23:14 -070050
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040051import javax.inject.Inject;
52import javax.inject.Singleton;
53
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070054/**
Selim Cineke70d6532015-04-24 16:46:13 -070055 * Class to manage everything related to assist in SystemUI.
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070056 */
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040057@Singleton
Dave Mankoffbba732d2019-11-20 13:04:54 -050058public class AssistManager {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070059
Miranda Kephart433c8112019-05-22 12:25:51 -040060 /**
61 * Controls the UI for showing Assistant invocation progress.
62 */
63 public interface UiController {
64 /**
65 * Updates the invocation progress.
66 *
67 * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
68 * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
69 * INVOCATION_HOME_BUTTON_LONG_PRESS
70 * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
71 * gesture; 1 represents the end.
72 */
73 void onInvocationProgress(int type, float progress);
74
75 /**
76 * Called when an invocation gesture completes.
77 *
78 * @param velocity the speed of the invocation gesture, in pixels per millisecond. For
79 * drags, this is 0.
80 */
81 void onGestureCompletion(float velocity);
82
83 /**
84 * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints.
85 */
86 void processBundle(Bundle hints);
87
88 /**
James O'Leary7b92b122019-07-09 12:43:45 -040089 * Hides any SysUI for the assistant, but _does not_ close the assistant itself.
Miranda Kephart433c8112019-05-22 12:25:51 -040090 */
91 void hide();
92 }
93
Selim Cineke70d6532015-04-24 16:46:13 -070094 private static final String TAG = "AssistManager";
Matt Casey4cff16f2019-01-14 14:56:06 -050095
96 // Note that VERBOSE logging may leak PII (e.g. transcription contents).
97 private static final boolean VERBOSE = false;
98
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070099 private static final String ASSIST_ICON_METADATA_NAME =
100 "com.android.systemui.action_assist_icon";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400101 private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
Govinda Wassermana2c887602019-05-08 08:02:47 -0400102 private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400103 public static final String INVOCATION_TYPE_KEY = "invocation_type";
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700104 protected static final String ACTION_KEY = "action";
105 protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400106
107 public static final int INVOCATION_TYPE_GESTURE = 1;
108 public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
109 public static final int INVOCATION_TYPE_VOICE = 3;
110 public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
111 public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700112
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400113 public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
114 public static final int DISMISS_REASON_TAP = 2;
115 public static final int DISMISS_REASON_BACK = 3;
116 public static final int DISMISS_REASON_TIMEOUT = 4;
117
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700118 private static final long TIMEOUT_SERVICE = 2500;
119 private static final long TIMEOUT_ACTIVITY = 1000;
120
Annie Chin4c249ff2016-07-08 14:52:00 -0700121 protected final Context mContext;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700122 private final WindowManager mWindowManager;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700123 private final AssistDisclosure mAssistDisclosure;
Jason Monk9c7844c2017-01-18 15:21:53 -0500124 private final InterestingConfigChanges mInterestingConfigChanges;
Govinda Wassermana2c887602019-05-08 08:02:47 -0400125 private final PhoneStateMonitor mPhoneStateMonitor;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400126 private final AssistHandleBehaviorController mHandleController;
Miranda Kephart433c8112019-05-22 12:25:51 -0400127 private final UiController mUiController;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700128
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700129 private AssistOrbContainer mView;
Jason Monk9c7844c2017-01-18 15:21:53 -0500130 private final DeviceProvisionedController mDeviceProvisionedController;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400131 private final CommandQueue mCommandQueue;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700132 protected final AssistUtils mAssistUtils;
Rajeev Kumar3e084302017-09-25 19:08:12 -0700133 private final boolean mShouldEnableOrb;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700134
135 private IVoiceInteractionSessionShowCallback mShowCallback =
136 new IVoiceInteractionSessionShowCallback.Stub() {
137
Miranda Kephart433c8112019-05-22 12:25:51 -0400138 @Override
139 public void onFailed() throws RemoteException {
140 mView.post(mHideRunnable);
141 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700142
Miranda Kephart433c8112019-05-22 12:25:51 -0400143 @Override
144 public void onShown() throws RemoteException {
145 mView.post(mHideRunnable);
146 }
147 };
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700148
149 private Runnable mHideRunnable = new Runnable() {
150 @Override
151 public void run() {
152 mView.removeCallbacks(this);
153 mView.show(false /* show */, true /* animate */);
154 }
155 };
156
Dave Mankoffbba732d2019-11-20 13:04:54 -0500157 private ConfigurationController.ConfigurationListener mConfigurationListener =
158 new ConfigurationController.ConfigurationListener() {
159 @Override
160 public void onConfigChanged(Configuration newConfig) {
161 if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
162 return;
163 }
164 boolean visible = false;
165 if (mView != null) {
166 visible = mView.isShowing();
167 mWindowManager.removeView(mView);
168 }
169
170 mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
171 R.layout.assist_orb, null);
172 mView.setVisibility(View.GONE);
173 mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
174 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
175 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
176 WindowManager.LayoutParams lp = getLayoutParams();
177 mWindowManager.addView(mView, lp);
178 if (visible) {
179 mView.show(true /* show */, false /* animate */);
180 }
181 }
182 };
183
Govinda Wasserman2e86fb62019-08-13 11:35:44 -0400184 @Inject
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400185 public AssistManager(
186 DeviceProvisionedController controller,
187 Context context,
188 AssistUtils assistUtils,
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400189 AssistHandleBehaviorController handleController,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000190 CommandQueue commandQueue,
Dave Mankoff4dd47fa2019-11-07 10:44:48 -0500191 PhoneStateMonitor phoneStateMonitor,
Dave Mankoffbba732d2019-11-20 13:04:54 -0500192 OverviewProxyService overviewProxyService,
193 ConfigurationController configurationController) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700194 mContext = context;
Jason Monk9c7844c2017-01-18 15:21:53 -0500195 mDeviceProvisionedController = controller;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400196 mCommandQueue = commandQueue;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700197 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400198 mAssistUtils = assistUtils;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700199 mAssistDisclosure = new AssistDisclosure(context, new Handler());
Dave Mankoff4dd47fa2019-11-07 10:44:48 -0500200 mPhoneStateMonitor = phoneStateMonitor;
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400201 mHandleController = handleController;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700202
Dave Mankoffbba732d2019-11-20 13:04:54 -0500203 configurationController.addCallback(mConfigurationListener);
204
Annie Chinecb9f3e2016-06-27 16:01:52 -0700205 registerVoiceInteractionSessionListener();
Jason Monk3edad312017-06-05 11:33:48 -0400206 mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
207 | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
208 | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
Dave Mankoffbba732d2019-11-20 13:04:54 -0500209 mConfigurationListener.onConfigChanged(context.getResources().getConfiguration());
Rajeev Kumar3e084302017-09-25 19:08:12 -0700210 mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
Miranda Kephart433c8112019-05-22 12:25:51 -0400211
212 mUiController = new DefaultUiController(mContext);
213
Dave Mankoff4dd47fa2019-11-07 10:44:48 -0500214 overviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() {
Miranda Kephart433c8112019-05-22 12:25:51 -0400215 @Override
216 public void onAssistantProgress(float progress) {
217 // Progress goes from 0 to 1 to indicate how close the assist gesture is to
218 // completion.
219 onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
220 }
221
222 @Override
223 public void onAssistantGestureCompletion(float velocity) {
224 onGestureCompletion(velocity);
225 }
226 });
Annie Chinecb9f3e2016-06-27 16:01:52 -0700227 }
228
229 protected void registerVoiceInteractionSessionListener() {
230 mAssistUtils.registerVoiceInteractionSessionListener(
231 new IVoiceInteractionSessionListener.Stub() {
Matt Casey4cff16f2019-01-14 14:56:06 -0500232 @Override
233 public void onVoiceSessionShown() throws RemoteException {
234 if (VERBOSE) {
235 Log.v(TAG, "Voice open");
236 }
237 }
Annie Chinecb9f3e2016-06-27 16:01:52 -0700238
Matt Casey4cff16f2019-01-14 14:56:06 -0500239 @Override
240 public void onVoiceSessionHidden() throws RemoteException {
241 if (VERBOSE) {
242 Log.v(TAG, "Voice closed");
243 }
244 }
245
246 @Override
James O'Leary9c9dd982019-02-08 15:49:06 -0500247 public void onSetUiHints(Bundle hints) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500248 if (VERBOSE) {
James O'Leary9c9dd982019-02-08 15:49:06 -0500249 Log.v(TAG, "UI hints received");
Matt Casey4cff16f2019-01-14 14:56:06 -0500250 }
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700251 if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) {
252 requestAssistHandles();
253 }
Matt Casey4cff16f2019-01-14 14:56:06 -0500254 }
255 });
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700256 }
257
Annie Chin937a9912016-05-31 10:14:23 -0700258 protected boolean shouldShowOrb() {
jschungfc5e15c2019-05-08 11:11:59 +0900259 return false;
Annie Chin937a9912016-05-31 10:14:23 -0700260 }
261
Jorim Jaggi165ce062015-07-06 16:18:11 -0700262 public void startAssist(Bundle args) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700263 final ComponentName assistComponent = getAssistInfo();
264 if (assistComponent == null) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700265 return;
266 }
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700267
Yohei Yukawa528e4682015-09-10 22:21:04 -0700268 final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
Annie Chin937a9912016-05-31 10:14:23 -0700269 if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700270 showOrb(assistComponent, isService);
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700271 mView.postDelayed(mHideRunnable, isService
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700272 ? TIMEOUT_SERVICE
273 : TIMEOUT_ACTIVITY);
274 }
Dan Sandler62bdce52019-04-23 19:18:21 -0400275
276 if (args == null) {
277 args = new Bundle();
278 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400279 int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
280 if (invocationType == INVOCATION_TYPE_GESTURE) {
281 mHandleController.onAssistantGesturePerformed();
282 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400283 int phoneState = mPhoneStateMonitor.getPhoneState();
284 args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
Govinda Wasserman6445e682019-06-04 09:37:32 -0400285 args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
Govinda Wasserman6418e972019-06-03 12:37:43 -0400286 logStartAssist(invocationType, phoneState);
Yohei Yukawa528e4682015-09-10 22:21:04 -0700287 startAssistInternal(args, assistComponent, isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700288 }
289
Govinda Wassermanb130e942019-04-15 10:07:37 -0400290 /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
291 public void onInvocationProgress(int type, float progress) {
Miranda Kephart433c8112019-05-22 12:25:51 -0400292 mUiController.onInvocationProgress(type, progress);
Govinda Wassermanb130e942019-04-15 10:07:37 -0400293 }
294
Miranda Kephart433c8112019-05-22 12:25:51 -0400295 /**
296 * Called when the user has invoked the assistant with the incoming velocity, in pixels per
Miranda Kephart4be26902019-05-17 13:55:37 -0400297 * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
298 * zero.
299 */
Miranda Kephart433c8112019-05-22 12:25:51 -0400300 public void onGestureCompletion(float velocity) {
301 mUiController.onGestureCompletion(velocity);
Miranda Kephart4be26902019-05-17 13:55:37 -0400302 }
303
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700304 protected void requestAssistHandles() {
305 mHandleController.onAssistHandlesRequested();
306 }
307
Jorim Jaggib835dd72015-06-08 12:28:42 -0700308 public void hideAssist() {
Adrian Roose9175082015-06-15 13:23:14 -0700309 mAssistUtils.hideCurrentSession();
Jorim Jaggib835dd72015-06-08 12:28:42 -0700310 }
311
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700312 private WindowManager.LayoutParams getLayoutParams() {
313 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
314 ViewGroup.LayoutParams.MATCH_PARENT,
315 mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
316 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
317 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
318 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
319 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
320 PixelFormat.TRANSLUCENT);
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800321 lp.token = new Binder();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700322 lp.gravity = Gravity.BOTTOM | Gravity.START;
323 lp.setTitle("AssistPreviewPanel");
324 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
325 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
326 return lp;
327 }
328
Yohei Yukawa528e4682015-09-10 22:21:04 -0700329 private void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
330 maybeSwapSearchIcon(assistComponent, isService);
Rajeev Kumar3e084302017-09-25 19:08:12 -0700331 if (mShouldEnableOrb) {
332 mView.show(true /* show */, true /* animate */);
333 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700334 }
335
Yohei Yukawa528e4682015-09-10 22:21:04 -0700336 private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent,
337 boolean isService) {
338 if (isService) {
339 startVoiceInteractor(args);
340 } else {
341 startAssistActivity(args, assistComponent);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700342 }
343 }
344
Yohei Yukawa528e4682015-09-10 22:21:04 -0700345 private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500346 if (!mDeviceProvisionedController.isDeviceProvisioned()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700347 return;
348 }
349
350 // Close Recent Apps if needed
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400351 mCommandQueue.animateCollapsePanels(
Jason Monk297c04e2018-08-23 17:16:59 -0400352 CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
353 false /* force */);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700354
Adrian Roos4f43dc02015-06-17 16:43:38 -0700355 boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
356 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
357
Steven Wu2b71d792018-05-08 11:03:17 -0400358 final SearchManager searchManager =
Miranda Kephart433c8112019-05-22 12:25:51 -0400359 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
Steven Wu2b71d792018-05-08 11:03:17 -0400360 if (searchManager == null) {
361 return;
362 }
363 final Intent intent = searchManager.getAssistIntent(structureEnabled);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700364 if (intent == null) {
365 return;
366 }
Yohei Yukawa528e4682015-09-10 22:21:04 -0700367 intent.setComponent(assistComponent);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700368 intent.putExtras(args);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700369
Rajeev Kumarcd497ef2019-08-06 12:02:47 -0700370 if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
Adrian Roos4f43dc02015-06-17 16:43:38 -0700371 showDisclosure();
372 }
373
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700374 try {
375 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
376 R.anim.search_launch_enter, R.anim.search_launch_exit);
377 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
378 AsyncTask.execute(new Runnable() {
379 @Override
380 public void run() {
381 mContext.startActivityAsUser(intent, opts.toBundle(),
382 new UserHandle(UserHandle.USER_CURRENT));
383 }
384 });
385 } catch (ActivityNotFoundException e) {
386 Log.w(TAG, "Activity not found for " + intent.getAction());
387 }
388 }
389
Jorim Jaggi165ce062015-07-06 16:18:11 -0700390 private void startVoiceInteractor(Bundle args) {
Dianne Hackborn17f69352015-07-17 18:04:14 -0700391 mAssistUtils.showSessionForActiveService(args,
392 VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700393 }
394
Selim Cineke70d6532015-04-24 16:46:13 -0700395 public void launchVoiceAssistFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700396 mAssistUtils.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700397 }
398
Selim Cineke70d6532015-04-24 16:46:13 -0700399 public boolean canVoiceAssistBeLaunchedFromKeyguard() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700400 // TODO(b/140051519)
401 return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard());
Selim Cineke70d6532015-04-24 16:46:13 -0700402 }
403
404 public ComponentName getVoiceInteractorComponentName() {
Adrian Roose9175082015-06-15 13:23:14 -0700405 return mAssistUtils.getActiveServiceComponentName();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700406 }
407
408 private boolean isVoiceSessionRunning() {
Adrian Roose9175082015-06-15 13:23:14 -0700409 return mAssistUtils.isSessionRunning();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700410 }
411
Yohei Yukawa528e4682015-09-10 22:21:04 -0700412 private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
413 replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
414 isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700415 }
416
417 public void replaceDrawable(ImageView v, ComponentName component, String name,
418 boolean isService) {
419 if (component != null) {
420 try {
421 PackageManager packageManager = mContext.getPackageManager();
422 // Look for the search icon specified in the activity meta-data
423 Bundle metaData = isService
424 ? packageManager.getServiceInfo(
Miranda Kephart433c8112019-05-22 12:25:51 -0400425 component, PackageManager.GET_META_DATA).metaData
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700426 : packageManager.getActivityInfo(
427 component, PackageManager.GET_META_DATA).metaData;
428 if (metaData != null) {
429 int iconResId = metaData.getInt(name);
430 if (iconResId != 0) {
431 Resources res = packageManager.getResourcesForApplication(
432 component.getPackageName());
433 v.setImageDrawable(res.getDrawable(iconResId));
434 return;
435 }
436 }
437 } catch (PackageManager.NameNotFoundException e) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500438 if (VERBOSE) {
439 Log.v(TAG, "Assistant component "
440 + component.flattenToShortString() + " not found");
441 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700442 } catch (Resources.NotFoundException nfe) {
443 Log.w(TAG, "Failed to swap drawable from "
444 + component.flattenToShortString(), nfe);
445 }
446 }
447 v.setImageDrawable(null);
448 }
449
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400450 protected AssistHandleBehaviorController getHandleBehaviorController() {
451 return mHandleController;
452 }
453
Yohei Yukawa528e4682015-09-10 22:21:04 -0700454 @Nullable
Matthew Ngadd4c392019-03-01 16:02:31 -0800455 public ComponentName getAssistInfoForUser(int userId) {
456 return mAssistUtils.getAssistComponentForUser(userId);
457 }
458
459 @Nullable
Yohei Yukawa528e4682015-09-10 22:21:04 -0700460 private ComponentName getAssistInfo() {
Matthew Ngadd4c392019-03-01 16:02:31 -0800461 return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700462 }
Adrian Roos4f43dc02015-06-17 16:43:38 -0700463
464 public void showDisclosure() {
465 mAssistDisclosure.postShow();
466 }
Selim Cinek9a634992015-06-23 01:10:07 -0400467
Jorim Jaggi19695d92015-07-20 15:51:40 -0700468 public void onLockscreenShown() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700469 // TODO(b/140052478)
470 whitelistIpcs(mAssistUtils::onLockscreenShown);
Jorim Jaggi19695d92015-07-20 15:51:40 -0700471 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400472
Govinda Wassermane9ff1ff2019-07-31 15:26:33 -0400473 public long getAssistHandleShowAndGoRemainingDurationMs() {
474 return mHandleController.getShowAndGoRemainingTimeMs();
475 }
476
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400477 /** Returns the logging flags for the given Assistant invocation type. */
478 public int toLoggingSubType(int invocationType) {
479 return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
480 }
481
Govinda Wasserman6418e972019-06-03 12:37:43 -0400482 protected void logStartAssist(int invocationType, int phoneState) {
483 MetricsLogger.action(
484 new LogMaker(MetricsEvent.ASSISTANT)
485 .setType(MetricsEvent.TYPE_OPEN)
486 .setSubtype(toLoggingSubType(invocationType, phoneState)));
487 }
488
489 protected final int toLoggingSubType(int invocationType, int phoneState) {
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400490 // Note that this logic will break if the number of Assistant invocation types exceeds 7.
491 // There are currently 5 invocation types, but we will be migrating to the new logging
492 // framework in the next update.
493 int subType = mHandleController.areHandlesShowing() ? 0 : 1;
494 subType |= invocationType << 1;
495 subType |= phoneState << 4;
496 return subType;
497 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700498}