blob: 398826c552bddbb8f4a37db45235691110f0ab52 [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;
44import com.android.systemui.ConfigurationChangedReceiver;
Miranda Kephart433c8112019-05-22 12:25:51 -040045import com.android.systemui.Dependency;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070046import com.android.systemui.R;
Miranda Kephart433c8112019-05-22 12:25:51 -040047import com.android.systemui.assist.ui.DefaultUiController;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000048import com.android.systemui.broadcast.BroadcastDispatcher;
Miranda Kephart433c8112019-05-22 12:25:51 -040049import com.android.systemui.recents.OverviewProxyService;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070050import com.android.systemui.statusbar.CommandQueue;
Jason Monk9c7844c2017-01-18 15:21:53 -050051import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Adrian Roose9175082015-06-15 13:23:14 -070052
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040053import javax.inject.Inject;
54import javax.inject.Singleton;
55
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070056/**
Selim Cineke70d6532015-04-24 16:46:13 -070057 * Class to manage everything related to assist in SystemUI.
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070058 */
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040059@Singleton
Jason Monk9c7844c2017-01-18 15:21:53 -050060public class AssistManager implements ConfigurationChangedReceiver {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070061
Miranda Kephart433c8112019-05-22 12:25:51 -040062 /**
63 * Controls the UI for showing Assistant invocation progress.
64 */
65 public interface UiController {
66 /**
67 * Updates the invocation progress.
68 *
69 * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
70 * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
71 * INVOCATION_HOME_BUTTON_LONG_PRESS
72 * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
73 * gesture; 1 represents the end.
74 */
75 void onInvocationProgress(int type, float progress);
76
77 /**
78 * Called when an invocation gesture completes.
79 *
80 * @param velocity the speed of the invocation gesture, in pixels per millisecond. For
81 * drags, this is 0.
82 */
83 void onGestureCompletion(float velocity);
84
85 /**
86 * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints.
87 */
88 void processBundle(Bundle hints);
89
90 /**
James O'Leary7b92b122019-07-09 12:43:45 -040091 * Hides any SysUI for the assistant, but _does not_ close the assistant itself.
Miranda Kephart433c8112019-05-22 12:25:51 -040092 */
93 void hide();
94 }
95
Selim Cineke70d6532015-04-24 16:46:13 -070096 private static final String TAG = "AssistManager";
Matt Casey4cff16f2019-01-14 14:56:06 -050097
98 // Note that VERBOSE logging may leak PII (e.g. transcription contents).
99 private static final boolean VERBOSE = false;
100
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700101 private static final String ASSIST_ICON_METADATA_NAME =
102 "com.android.systemui.action_assist_icon";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400103 private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
Govinda Wassermana2c887602019-05-08 08:02:47 -0400104 private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400105 public static final String INVOCATION_TYPE_KEY = "invocation_type";
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700106 protected static final String ACTION_KEY = "action";
107 protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400108
109 public static final int INVOCATION_TYPE_GESTURE = 1;
110 public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
111 public static final int INVOCATION_TYPE_VOICE = 3;
112 public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
113 public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700114
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400115 public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
116 public static final int DISMISS_REASON_TAP = 2;
117 public static final int DISMISS_REASON_BACK = 3;
118 public static final int DISMISS_REASON_TIMEOUT = 4;
119
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700120 private static final long TIMEOUT_SERVICE = 2500;
121 private static final long TIMEOUT_ACTIVITY = 1000;
122
Annie Chin4c249ff2016-07-08 14:52:00 -0700123 protected final Context mContext;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700124 private final WindowManager mWindowManager;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700125 private final AssistDisclosure mAssistDisclosure;
Jason Monk9c7844c2017-01-18 15:21:53 -0500126 private final InterestingConfigChanges mInterestingConfigChanges;
Govinda Wassermana2c887602019-05-08 08:02:47 -0400127 private final PhoneStateMonitor mPhoneStateMonitor;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400128 private final AssistHandleBehaviorController mHandleController;
Miranda Kephart433c8112019-05-22 12:25:51 -0400129 private final UiController mUiController;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700130
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700131 private AssistOrbContainer mView;
Jason Monk9c7844c2017-01-18 15:21:53 -0500132 private final DeviceProvisionedController mDeviceProvisionedController;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400133 private final CommandQueue mCommandQueue;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700134 protected final AssistUtils mAssistUtils;
Rajeev Kumar3e084302017-09-25 19:08:12 -0700135 private final boolean mShouldEnableOrb;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700136
137 private IVoiceInteractionSessionShowCallback mShowCallback =
138 new IVoiceInteractionSessionShowCallback.Stub() {
139
Miranda Kephart433c8112019-05-22 12:25:51 -0400140 @Override
141 public void onFailed() throws RemoteException {
142 mView.post(mHideRunnable);
143 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700144
Miranda Kephart433c8112019-05-22 12:25:51 -0400145 @Override
146 public void onShown() throws RemoteException {
147 mView.post(mHideRunnable);
148 }
149 };
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700150
151 private Runnable mHideRunnable = new Runnable() {
152 @Override
153 public void run() {
154 mView.removeCallbacks(this);
155 mView.show(false /* show */, true /* animate */);
156 }
157 };
158
Govinda Wasserman2e86fb62019-08-13 11:35:44 -0400159 @Inject
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400160 public AssistManager(
161 DeviceProvisionedController controller,
162 Context context,
163 AssistUtils assistUtils,
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400164 AssistHandleBehaviorController handleController,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000165 CommandQueue commandQueue,
166 BroadcastDispatcher broadcastDispatcher) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700167 mContext = context;
Jason Monk9c7844c2017-01-18 15:21:53 -0500168 mDeviceProvisionedController = controller;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400169 mCommandQueue = commandQueue;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700170 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400171 mAssistUtils = assistUtils;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700172 mAssistDisclosure = new AssistDisclosure(context, new Handler());
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000173 mPhoneStateMonitor = new PhoneStateMonitor(context, broadcastDispatcher);
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400174 mHandleController = handleController;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700175
176 registerVoiceInteractionSessionListener();
Jason Monk3edad312017-06-05 11:33:48 -0400177 mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
178 | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
179 | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
Jason Monk9c7844c2017-01-18 15:21:53 -0500180 onConfigurationChanged(context.getResources().getConfiguration());
Rajeev Kumar3e084302017-09-25 19:08:12 -0700181 mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
Miranda Kephart433c8112019-05-22 12:25:51 -0400182
183 mUiController = new DefaultUiController(mContext);
184
185 OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class);
186 overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() {
187 @Override
188 public void onAssistantProgress(float progress) {
189 // Progress goes from 0 to 1 to indicate how close the assist gesture is to
190 // completion.
191 onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
192 }
193
194 @Override
195 public void onAssistantGestureCompletion(float velocity) {
196 onGestureCompletion(velocity);
197 }
198 });
Annie Chinecb9f3e2016-06-27 16:01:52 -0700199 }
200
201 protected void registerVoiceInteractionSessionListener() {
202 mAssistUtils.registerVoiceInteractionSessionListener(
203 new IVoiceInteractionSessionListener.Stub() {
Matt Casey4cff16f2019-01-14 14:56:06 -0500204 @Override
205 public void onVoiceSessionShown() throws RemoteException {
206 if (VERBOSE) {
207 Log.v(TAG, "Voice open");
208 }
209 }
Annie Chinecb9f3e2016-06-27 16:01:52 -0700210
Matt Casey4cff16f2019-01-14 14:56:06 -0500211 @Override
212 public void onVoiceSessionHidden() throws RemoteException {
213 if (VERBOSE) {
214 Log.v(TAG, "Voice closed");
215 }
216 }
217
218 @Override
James O'Leary9c9dd982019-02-08 15:49:06 -0500219 public void onSetUiHints(Bundle hints) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500220 if (VERBOSE) {
James O'Leary9c9dd982019-02-08 15:49:06 -0500221 Log.v(TAG, "UI hints received");
Matt Casey4cff16f2019-01-14 14:56:06 -0500222 }
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700223 if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) {
224 requestAssistHandles();
225 }
Matt Casey4cff16f2019-01-14 14:56:06 -0500226 }
227 });
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700228 }
229
Jason Monk9c7844c2017-01-18 15:21:53 -0500230 public void onConfigurationChanged(Configuration newConfiguration) {
231 if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
232 return;
233 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700234 boolean visible = false;
235 if (mView != null) {
236 visible = mView.isShowing();
237 mWindowManager.removeView(mView);
238 }
239
240 mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
241 R.layout.assist_orb, null);
242 mView.setVisibility(View.GONE);
243 mView.setSystemUiVisibility(
244 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
245 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
246 WindowManager.LayoutParams lp = getLayoutParams();
247 mWindowManager.addView(mView, lp);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700248 if (visible) {
249 mView.show(true /* show */, false /* animate */);
250 }
251 }
252
Annie Chin937a9912016-05-31 10:14:23 -0700253 protected boolean shouldShowOrb() {
jschungfc5e15c2019-05-08 11:11:59 +0900254 return false;
Annie Chin937a9912016-05-31 10:14:23 -0700255 }
256
Jorim Jaggi165ce062015-07-06 16:18:11 -0700257 public void startAssist(Bundle args) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700258 final ComponentName assistComponent = getAssistInfo();
259 if (assistComponent == null) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700260 return;
261 }
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700262
Yohei Yukawa528e4682015-09-10 22:21:04 -0700263 final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
Annie Chin937a9912016-05-31 10:14:23 -0700264 if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700265 showOrb(assistComponent, isService);
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700266 mView.postDelayed(mHideRunnable, isService
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700267 ? TIMEOUT_SERVICE
268 : TIMEOUT_ACTIVITY);
269 }
Dan Sandler62bdce52019-04-23 19:18:21 -0400270
271 if (args == null) {
272 args = new Bundle();
273 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400274 int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
275 if (invocationType == INVOCATION_TYPE_GESTURE) {
276 mHandleController.onAssistantGesturePerformed();
277 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400278 int phoneState = mPhoneStateMonitor.getPhoneState();
279 args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
Govinda Wasserman6445e682019-06-04 09:37:32 -0400280 args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
Govinda Wasserman6418e972019-06-03 12:37:43 -0400281 logStartAssist(invocationType, phoneState);
Yohei Yukawa528e4682015-09-10 22:21:04 -0700282 startAssistInternal(args, assistComponent, isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700283 }
284
Govinda Wassermanb130e942019-04-15 10:07:37 -0400285 /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
286 public void onInvocationProgress(int type, float progress) {
Miranda Kephart433c8112019-05-22 12:25:51 -0400287 mUiController.onInvocationProgress(type, progress);
Govinda Wassermanb130e942019-04-15 10:07:37 -0400288 }
289
Miranda Kephart433c8112019-05-22 12:25:51 -0400290 /**
291 * Called when the user has invoked the assistant with the incoming velocity, in pixels per
Miranda Kephart4be26902019-05-17 13:55:37 -0400292 * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
293 * zero.
294 */
Miranda Kephart433c8112019-05-22 12:25:51 -0400295 public void onGestureCompletion(float velocity) {
296 mUiController.onGestureCompletion(velocity);
Miranda Kephart4be26902019-05-17 13:55:37 -0400297 }
298
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700299 protected void requestAssistHandles() {
300 mHandleController.onAssistHandlesRequested();
301 }
302
Jorim Jaggib835dd72015-06-08 12:28:42 -0700303 public void hideAssist() {
Adrian Roose9175082015-06-15 13:23:14 -0700304 mAssistUtils.hideCurrentSession();
Jorim Jaggib835dd72015-06-08 12:28:42 -0700305 }
306
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700307 private WindowManager.LayoutParams getLayoutParams() {
308 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
309 ViewGroup.LayoutParams.MATCH_PARENT,
310 mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
311 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
312 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
313 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
314 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
315 PixelFormat.TRANSLUCENT);
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800316 lp.token = new Binder();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700317 lp.gravity = Gravity.BOTTOM | Gravity.START;
318 lp.setTitle("AssistPreviewPanel");
319 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
320 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
321 return lp;
322 }
323
Yohei Yukawa528e4682015-09-10 22:21:04 -0700324 private void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
325 maybeSwapSearchIcon(assistComponent, isService);
Rajeev Kumar3e084302017-09-25 19:08:12 -0700326 if (mShouldEnableOrb) {
327 mView.show(true /* show */, true /* animate */);
328 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700329 }
330
Yohei Yukawa528e4682015-09-10 22:21:04 -0700331 private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent,
332 boolean isService) {
333 if (isService) {
334 startVoiceInteractor(args);
335 } else {
336 startAssistActivity(args, assistComponent);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700337 }
338 }
339
Yohei Yukawa528e4682015-09-10 22:21:04 -0700340 private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500341 if (!mDeviceProvisionedController.isDeviceProvisioned()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700342 return;
343 }
344
345 // Close Recent Apps if needed
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400346 mCommandQueue.animateCollapsePanels(
Jason Monk297c04e2018-08-23 17:16:59 -0400347 CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
348 false /* force */);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700349
Adrian Roos4f43dc02015-06-17 16:43:38 -0700350 boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
351 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
352
Steven Wu2b71d792018-05-08 11:03:17 -0400353 final SearchManager searchManager =
Miranda Kephart433c8112019-05-22 12:25:51 -0400354 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
Steven Wu2b71d792018-05-08 11:03:17 -0400355 if (searchManager == null) {
356 return;
357 }
358 final Intent intent = searchManager.getAssistIntent(structureEnabled);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700359 if (intent == null) {
360 return;
361 }
Yohei Yukawa528e4682015-09-10 22:21:04 -0700362 intent.setComponent(assistComponent);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700363 intent.putExtras(args);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700364
Rajeev Kumarcd497ef2019-08-06 12:02:47 -0700365 if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
Adrian Roos4f43dc02015-06-17 16:43:38 -0700366 showDisclosure();
367 }
368
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700369 try {
370 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
371 R.anim.search_launch_enter, R.anim.search_launch_exit);
372 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
373 AsyncTask.execute(new Runnable() {
374 @Override
375 public void run() {
376 mContext.startActivityAsUser(intent, opts.toBundle(),
377 new UserHandle(UserHandle.USER_CURRENT));
378 }
379 });
380 } catch (ActivityNotFoundException e) {
381 Log.w(TAG, "Activity not found for " + intent.getAction());
382 }
383 }
384
Jorim Jaggi165ce062015-07-06 16:18:11 -0700385 private void startVoiceInteractor(Bundle args) {
Dianne Hackborn17f69352015-07-17 18:04:14 -0700386 mAssistUtils.showSessionForActiveService(args,
387 VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700388 }
389
Selim Cineke70d6532015-04-24 16:46:13 -0700390 public void launchVoiceAssistFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700391 mAssistUtils.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700392 }
393
Selim Cineke70d6532015-04-24 16:46:13 -0700394 public boolean canVoiceAssistBeLaunchedFromKeyguard() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700395 // TODO(b/140051519)
396 return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard());
Selim Cineke70d6532015-04-24 16:46:13 -0700397 }
398
399 public ComponentName getVoiceInteractorComponentName() {
Adrian Roose9175082015-06-15 13:23:14 -0700400 return mAssistUtils.getActiveServiceComponentName();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700401 }
402
403 private boolean isVoiceSessionRunning() {
Adrian Roose9175082015-06-15 13:23:14 -0700404 return mAssistUtils.isSessionRunning();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700405 }
406
Yohei Yukawa528e4682015-09-10 22:21:04 -0700407 private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
408 replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
409 isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700410 }
411
412 public void replaceDrawable(ImageView v, ComponentName component, String name,
413 boolean isService) {
414 if (component != null) {
415 try {
416 PackageManager packageManager = mContext.getPackageManager();
417 // Look for the search icon specified in the activity meta-data
418 Bundle metaData = isService
419 ? packageManager.getServiceInfo(
Miranda Kephart433c8112019-05-22 12:25:51 -0400420 component, PackageManager.GET_META_DATA).metaData
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700421 : packageManager.getActivityInfo(
422 component, PackageManager.GET_META_DATA).metaData;
423 if (metaData != null) {
424 int iconResId = metaData.getInt(name);
425 if (iconResId != 0) {
426 Resources res = packageManager.getResourcesForApplication(
427 component.getPackageName());
428 v.setImageDrawable(res.getDrawable(iconResId));
429 return;
430 }
431 }
432 } catch (PackageManager.NameNotFoundException e) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500433 if (VERBOSE) {
434 Log.v(TAG, "Assistant component "
435 + component.flattenToShortString() + " not found");
436 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700437 } catch (Resources.NotFoundException nfe) {
438 Log.w(TAG, "Failed to swap drawable from "
439 + component.flattenToShortString(), nfe);
440 }
441 }
442 v.setImageDrawable(null);
443 }
444
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400445 protected AssistHandleBehaviorController getHandleBehaviorController() {
446 return mHandleController;
447 }
448
Yohei Yukawa528e4682015-09-10 22:21:04 -0700449 @Nullable
Matthew Ngadd4c392019-03-01 16:02:31 -0800450 public ComponentName getAssistInfoForUser(int userId) {
451 return mAssistUtils.getAssistComponentForUser(userId);
452 }
453
454 @Nullable
Yohei Yukawa528e4682015-09-10 22:21:04 -0700455 private ComponentName getAssistInfo() {
Matthew Ngadd4c392019-03-01 16:02:31 -0800456 return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700457 }
Adrian Roos4f43dc02015-06-17 16:43:38 -0700458
459 public void showDisclosure() {
460 mAssistDisclosure.postShow();
461 }
Selim Cinek9a634992015-06-23 01:10:07 -0400462
Jorim Jaggi19695d92015-07-20 15:51:40 -0700463 public void onLockscreenShown() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700464 // TODO(b/140052478)
465 whitelistIpcs(mAssistUtils::onLockscreenShown);
Jorim Jaggi19695d92015-07-20 15:51:40 -0700466 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400467
Govinda Wassermane9ff1ff2019-07-31 15:26:33 -0400468 public long getAssistHandleShowAndGoRemainingDurationMs() {
469 return mHandleController.getShowAndGoRemainingTimeMs();
470 }
471
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400472 /** Returns the logging flags for the given Assistant invocation type. */
473 public int toLoggingSubType(int invocationType) {
474 return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
475 }
476
Govinda Wasserman6418e972019-06-03 12:37:43 -0400477 protected void logStartAssist(int invocationType, int phoneState) {
478 MetricsLogger.action(
479 new LogMaker(MetricsEvent.ASSISTANT)
480 .setType(MetricsEvent.TYPE_OPEN)
481 .setSubtype(toLoggingSubType(invocationType, phoneState)));
482 }
483
484 protected final int toLoggingSubType(int invocationType, int phoneState) {
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400485 // Note that this logic will break if the number of Assistant invocation types exceeds 7.
486 // There are currently 5 invocation types, but we will be migrating to the new logging
487 // framework in the next update.
488 int subType = mHandleController.areHandlesShowing() ? 0 : 1;
489 subType |= invocationType << 1;
490 subType |= phoneState << 4;
491 return subType;
492 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700493}