blob: b7a6167df6bca0ce1336de43b001dfbac5ffead2 [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;
48import com.android.systemui.recents.OverviewProxyService;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070049import com.android.systemui.statusbar.CommandQueue;
Jason Monk9c7844c2017-01-18 15:21:53 -050050import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Adrian Roose9175082015-06-15 13:23:14 -070051
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040052import javax.inject.Inject;
53import javax.inject.Singleton;
54
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070055/**
Selim Cineke70d6532015-04-24 16:46:13 -070056 * Class to manage everything related to assist in SystemUI.
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070057 */
Govinda Wasserman2e86fb62019-08-13 11:35:44 -040058@Singleton
Jason Monk9c7844c2017-01-18 15:21:53 -050059public class AssistManager implements ConfigurationChangedReceiver {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070060
Miranda Kephart433c8112019-05-22 12:25:51 -040061 /**
62 * Controls the UI for showing Assistant invocation progress.
63 */
64 public interface UiController {
65 /**
66 * Updates the invocation progress.
67 *
68 * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
69 * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
70 * INVOCATION_HOME_BUTTON_LONG_PRESS
71 * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
72 * gesture; 1 represents the end.
73 */
74 void onInvocationProgress(int type, float progress);
75
76 /**
77 * Called when an invocation gesture completes.
78 *
79 * @param velocity the speed of the invocation gesture, in pixels per millisecond. For
80 * drags, this is 0.
81 */
82 void onGestureCompletion(float velocity);
83
84 /**
85 * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints.
86 */
87 void processBundle(Bundle hints);
88
89 /**
James O'Leary7b92b122019-07-09 12:43:45 -040090 * Hides any SysUI for the assistant, but _does not_ close the assistant itself.
Miranda Kephart433c8112019-05-22 12:25:51 -040091 */
92 void hide();
93 }
94
Selim Cineke70d6532015-04-24 16:46:13 -070095 private static final String TAG = "AssistManager";
Matt Casey4cff16f2019-01-14 14:56:06 -050096
97 // Note that VERBOSE logging may leak PII (e.g. transcription contents).
98 private static final boolean VERBOSE = false;
99
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700100 private static final String ASSIST_ICON_METADATA_NAME =
101 "com.android.systemui.action_assist_icon";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400102 private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
Govinda Wassermana2c887602019-05-08 08:02:47 -0400103 private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400104 public static final String INVOCATION_TYPE_KEY = "invocation_type";
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700105 protected static final String ACTION_KEY = "action";
106 protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -0400107
108 public static final int INVOCATION_TYPE_GESTURE = 1;
109 public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
110 public static final int INVOCATION_TYPE_VOICE = 3;
111 public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
112 public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700113
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400114 public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
115 public static final int DISMISS_REASON_TAP = 2;
116 public static final int DISMISS_REASON_BACK = 3;
117 public static final int DISMISS_REASON_TIMEOUT = 4;
118
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700119 private static final long TIMEOUT_SERVICE = 2500;
120 private static final long TIMEOUT_ACTIVITY = 1000;
121
Annie Chin4c249ff2016-07-08 14:52:00 -0700122 protected final Context mContext;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700123 private final WindowManager mWindowManager;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700124 private final AssistDisclosure mAssistDisclosure;
Jason Monk9c7844c2017-01-18 15:21:53 -0500125 private final InterestingConfigChanges mInterestingConfigChanges;
Govinda Wassermana2c887602019-05-08 08:02:47 -0400126 private final PhoneStateMonitor mPhoneStateMonitor;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400127 private final AssistHandleBehaviorController mHandleController;
Miranda Kephart433c8112019-05-22 12:25:51 -0400128 private final UiController mUiController;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700129
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700130 private AssistOrbContainer mView;
Jason Monk9c7844c2017-01-18 15:21:53 -0500131 private final DeviceProvisionedController mDeviceProvisionedController;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400132 private final CommandQueue mCommandQueue;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700133 protected final AssistUtils mAssistUtils;
Rajeev Kumar3e084302017-09-25 19:08:12 -0700134 private final boolean mShouldEnableOrb;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700135
136 private IVoiceInteractionSessionShowCallback mShowCallback =
137 new IVoiceInteractionSessionShowCallback.Stub() {
138
Miranda Kephart433c8112019-05-22 12:25:51 -0400139 @Override
140 public void onFailed() throws RemoteException {
141 mView.post(mHideRunnable);
142 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700143
Miranda Kephart433c8112019-05-22 12:25:51 -0400144 @Override
145 public void onShown() throws RemoteException {
146 mView.post(mHideRunnable);
147 }
148 };
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700149
150 private Runnable mHideRunnable = new Runnable() {
151 @Override
152 public void run() {
153 mView.removeCallbacks(this);
154 mView.show(false /* show */, true /* animate */);
155 }
156 };
157
Govinda Wasserman2e86fb62019-08-13 11:35:44 -0400158 @Inject
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400159 public AssistManager(
160 DeviceProvisionedController controller,
161 Context context,
162 AssistUtils assistUtils,
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400163 AssistHandleBehaviorController handleController,
164 CommandQueue commandQueue) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700165 mContext = context;
Jason Monk9c7844c2017-01-18 15:21:53 -0500166 mDeviceProvisionedController = controller;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400167 mCommandQueue = commandQueue;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700168 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400169 mAssistUtils = assistUtils;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700170 mAssistDisclosure = new AssistDisclosure(context, new Handler());
Govinda Wassermana2c887602019-05-08 08:02:47 -0400171 mPhoneStateMonitor = new PhoneStateMonitor(context);
Govinda Wasserman61c92d62019-09-05 16:32:23 -0400172 mHandleController = handleController;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700173
174 registerVoiceInteractionSessionListener();
Jason Monk3edad312017-06-05 11:33:48 -0400175 mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
176 | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
177 | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
Jason Monk9c7844c2017-01-18 15:21:53 -0500178 onConfigurationChanged(context.getResources().getConfiguration());
Rajeev Kumar3e084302017-09-25 19:08:12 -0700179 mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
Miranda Kephart433c8112019-05-22 12:25:51 -0400180
181 mUiController = new DefaultUiController(mContext);
182
183 OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class);
184 overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() {
185 @Override
186 public void onAssistantProgress(float progress) {
187 // Progress goes from 0 to 1 to indicate how close the assist gesture is to
188 // completion.
189 onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
190 }
191
192 @Override
193 public void onAssistantGestureCompletion(float velocity) {
194 onGestureCompletion(velocity);
195 }
196 });
Annie Chinecb9f3e2016-06-27 16:01:52 -0700197 }
198
199 protected void registerVoiceInteractionSessionListener() {
200 mAssistUtils.registerVoiceInteractionSessionListener(
201 new IVoiceInteractionSessionListener.Stub() {
Matt Casey4cff16f2019-01-14 14:56:06 -0500202 @Override
203 public void onVoiceSessionShown() throws RemoteException {
204 if (VERBOSE) {
205 Log.v(TAG, "Voice open");
206 }
207 }
Annie Chinecb9f3e2016-06-27 16:01:52 -0700208
Matt Casey4cff16f2019-01-14 14:56:06 -0500209 @Override
210 public void onVoiceSessionHidden() throws RemoteException {
211 if (VERBOSE) {
212 Log.v(TAG, "Voice closed");
213 }
214 }
215
216 @Override
James O'Leary9c9dd982019-02-08 15:49:06 -0500217 public void onSetUiHints(Bundle hints) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500218 if (VERBOSE) {
James O'Leary9c9dd982019-02-08 15:49:06 -0500219 Log.v(TAG, "UI hints received");
Matt Casey4cff16f2019-01-14 14:56:06 -0500220 }
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700221 if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) {
222 requestAssistHandles();
223 }
Matt Casey4cff16f2019-01-14 14:56:06 -0500224 }
225 });
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700226 }
227
Jason Monk9c7844c2017-01-18 15:21:53 -0500228 public void onConfigurationChanged(Configuration newConfiguration) {
229 if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
230 return;
231 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700232 boolean visible = false;
233 if (mView != null) {
234 visible = mView.isShowing();
235 mWindowManager.removeView(mView);
236 }
237
238 mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
239 R.layout.assist_orb, null);
240 mView.setVisibility(View.GONE);
241 mView.setSystemUiVisibility(
242 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
243 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
244 WindowManager.LayoutParams lp = getLayoutParams();
245 mWindowManager.addView(mView, lp);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700246 if (visible) {
247 mView.show(true /* show */, false /* animate */);
248 }
249 }
250
Annie Chin937a9912016-05-31 10:14:23 -0700251 protected boolean shouldShowOrb() {
jschungfc5e15c2019-05-08 11:11:59 +0900252 return false;
Annie Chin937a9912016-05-31 10:14:23 -0700253 }
254
Jorim Jaggi165ce062015-07-06 16:18:11 -0700255 public void startAssist(Bundle args) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700256 final ComponentName assistComponent = getAssistInfo();
257 if (assistComponent == null) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700258 return;
259 }
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700260
Yohei Yukawa528e4682015-09-10 22:21:04 -0700261 final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
Annie Chin937a9912016-05-31 10:14:23 -0700262 if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700263 showOrb(assistComponent, isService);
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700264 mView.postDelayed(mHideRunnable, isService
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700265 ? TIMEOUT_SERVICE
266 : TIMEOUT_ACTIVITY);
267 }
Dan Sandler62bdce52019-04-23 19:18:21 -0400268
269 if (args == null) {
270 args = new Bundle();
271 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400272 int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
273 if (invocationType == INVOCATION_TYPE_GESTURE) {
274 mHandleController.onAssistantGesturePerformed();
275 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400276 int phoneState = mPhoneStateMonitor.getPhoneState();
277 args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
Govinda Wasserman6445e682019-06-04 09:37:32 -0400278 args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
Govinda Wasserman6418e972019-06-03 12:37:43 -0400279 logStartAssist(invocationType, phoneState);
Yohei Yukawa528e4682015-09-10 22:21:04 -0700280 startAssistInternal(args, assistComponent, isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700281 }
282
Govinda Wassermanb130e942019-04-15 10:07:37 -0400283 /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
284 public void onInvocationProgress(int type, float progress) {
Miranda Kephart433c8112019-05-22 12:25:51 -0400285 mUiController.onInvocationProgress(type, progress);
Govinda Wassermanb130e942019-04-15 10:07:37 -0400286 }
287
Miranda Kephart433c8112019-05-22 12:25:51 -0400288 /**
289 * Called when the user has invoked the assistant with the incoming velocity, in pixels per
Miranda Kephart4be26902019-05-17 13:55:37 -0400290 * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
291 * zero.
292 */
Miranda Kephart433c8112019-05-22 12:25:51 -0400293 public void onGestureCompletion(float velocity) {
294 mUiController.onGestureCompletion(velocity);
Miranda Kephart4be26902019-05-17 13:55:37 -0400295 }
296
Hyunyoung Song8f9d34c2019-08-30 14:47:43 -0700297 protected void requestAssistHandles() {
298 mHandleController.onAssistHandlesRequested();
299 }
300
Jorim Jaggib835dd72015-06-08 12:28:42 -0700301 public void hideAssist() {
Adrian Roose9175082015-06-15 13:23:14 -0700302 mAssistUtils.hideCurrentSession();
Jorim Jaggib835dd72015-06-08 12:28:42 -0700303 }
304
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700305 private WindowManager.LayoutParams getLayoutParams() {
306 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
307 ViewGroup.LayoutParams.MATCH_PARENT,
308 mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
309 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
310 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
311 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
312 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
313 PixelFormat.TRANSLUCENT);
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800314 lp.token = new Binder();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700315 lp.gravity = Gravity.BOTTOM | Gravity.START;
316 lp.setTitle("AssistPreviewPanel");
317 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
318 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
319 return lp;
320 }
321
Yohei Yukawa528e4682015-09-10 22:21:04 -0700322 private void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
323 maybeSwapSearchIcon(assistComponent, isService);
Rajeev Kumar3e084302017-09-25 19:08:12 -0700324 if (mShouldEnableOrb) {
325 mView.show(true /* show */, true /* animate */);
326 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700327 }
328
Yohei Yukawa528e4682015-09-10 22:21:04 -0700329 private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent,
330 boolean isService) {
331 if (isService) {
332 startVoiceInteractor(args);
333 } else {
334 startAssistActivity(args, assistComponent);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700335 }
336 }
337
Yohei Yukawa528e4682015-09-10 22:21:04 -0700338 private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500339 if (!mDeviceProvisionedController.isDeviceProvisioned()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700340 return;
341 }
342
343 // Close Recent Apps if needed
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400344 mCommandQueue.animateCollapsePanels(
Jason Monk297c04e2018-08-23 17:16:59 -0400345 CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
346 false /* force */);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700347
Adrian Roos4f43dc02015-06-17 16:43:38 -0700348 boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
349 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
350
Steven Wu2b71d792018-05-08 11:03:17 -0400351 final SearchManager searchManager =
Miranda Kephart433c8112019-05-22 12:25:51 -0400352 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
Steven Wu2b71d792018-05-08 11:03:17 -0400353 if (searchManager == null) {
354 return;
355 }
356 final Intent intent = searchManager.getAssistIntent(structureEnabled);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700357 if (intent == null) {
358 return;
359 }
Yohei Yukawa528e4682015-09-10 22:21:04 -0700360 intent.setComponent(assistComponent);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700361 intent.putExtras(args);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700362
Rajeev Kumarcd497ef2019-08-06 12:02:47 -0700363 if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
Adrian Roos4f43dc02015-06-17 16:43:38 -0700364 showDisclosure();
365 }
366
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700367 try {
368 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
369 R.anim.search_launch_enter, R.anim.search_launch_exit);
370 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
371 AsyncTask.execute(new Runnable() {
372 @Override
373 public void run() {
374 mContext.startActivityAsUser(intent, opts.toBundle(),
375 new UserHandle(UserHandle.USER_CURRENT));
376 }
377 });
378 } catch (ActivityNotFoundException e) {
379 Log.w(TAG, "Activity not found for " + intent.getAction());
380 }
381 }
382
Jorim Jaggi165ce062015-07-06 16:18:11 -0700383 private void startVoiceInteractor(Bundle args) {
Dianne Hackborn17f69352015-07-17 18:04:14 -0700384 mAssistUtils.showSessionForActiveService(args,
385 VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700386 }
387
Selim Cineke70d6532015-04-24 16:46:13 -0700388 public void launchVoiceAssistFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700389 mAssistUtils.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700390 }
391
Selim Cineke70d6532015-04-24 16:46:13 -0700392 public boolean canVoiceAssistBeLaunchedFromKeyguard() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700393 // TODO(b/140051519)
394 return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard());
Selim Cineke70d6532015-04-24 16:46:13 -0700395 }
396
397 public ComponentName getVoiceInteractorComponentName() {
Adrian Roose9175082015-06-15 13:23:14 -0700398 return mAssistUtils.getActiveServiceComponentName();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700399 }
400
401 private boolean isVoiceSessionRunning() {
Adrian Roose9175082015-06-15 13:23:14 -0700402 return mAssistUtils.isSessionRunning();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700403 }
404
Yohei Yukawa528e4682015-09-10 22:21:04 -0700405 private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
406 replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
407 isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700408 }
409
410 public void replaceDrawable(ImageView v, ComponentName component, String name,
411 boolean isService) {
412 if (component != null) {
413 try {
414 PackageManager packageManager = mContext.getPackageManager();
415 // Look for the search icon specified in the activity meta-data
416 Bundle metaData = isService
417 ? packageManager.getServiceInfo(
Miranda Kephart433c8112019-05-22 12:25:51 -0400418 component, PackageManager.GET_META_DATA).metaData
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700419 : packageManager.getActivityInfo(
420 component, PackageManager.GET_META_DATA).metaData;
421 if (metaData != null) {
422 int iconResId = metaData.getInt(name);
423 if (iconResId != 0) {
424 Resources res = packageManager.getResourcesForApplication(
425 component.getPackageName());
426 v.setImageDrawable(res.getDrawable(iconResId));
427 return;
428 }
429 }
430 } catch (PackageManager.NameNotFoundException e) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500431 if (VERBOSE) {
432 Log.v(TAG, "Assistant component "
433 + component.flattenToShortString() + " not found");
434 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700435 } catch (Resources.NotFoundException nfe) {
436 Log.w(TAG, "Failed to swap drawable from "
437 + component.flattenToShortString(), nfe);
438 }
439 }
440 v.setImageDrawable(null);
441 }
442
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400443 protected AssistHandleBehaviorController getHandleBehaviorController() {
444 return mHandleController;
445 }
446
Yohei Yukawa528e4682015-09-10 22:21:04 -0700447 @Nullable
Matthew Ngadd4c392019-03-01 16:02:31 -0800448 public ComponentName getAssistInfoForUser(int userId) {
449 return mAssistUtils.getAssistComponentForUser(userId);
450 }
451
452 @Nullable
Yohei Yukawa528e4682015-09-10 22:21:04 -0700453 private ComponentName getAssistInfo() {
Matthew Ngadd4c392019-03-01 16:02:31 -0800454 return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700455 }
Adrian Roos4f43dc02015-06-17 16:43:38 -0700456
457 public void showDisclosure() {
458 mAssistDisclosure.postShow();
459 }
Selim Cinek9a634992015-06-23 01:10:07 -0400460
Jorim Jaggi19695d92015-07-20 15:51:40 -0700461 public void onLockscreenShown() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700462 // TODO(b/140052478)
463 whitelistIpcs(mAssistUtils::onLockscreenShown);
Jorim Jaggi19695d92015-07-20 15:51:40 -0700464 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400465
Govinda Wassermane9ff1ff2019-07-31 15:26:33 -0400466 public long getAssistHandleShowAndGoRemainingDurationMs() {
467 return mHandleController.getShowAndGoRemainingTimeMs();
468 }
469
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400470 /** Returns the logging flags for the given Assistant invocation type. */
471 public int toLoggingSubType(int invocationType) {
472 return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
473 }
474
Govinda Wasserman6418e972019-06-03 12:37:43 -0400475 protected void logStartAssist(int invocationType, int phoneState) {
476 MetricsLogger.action(
477 new LogMaker(MetricsEvent.ASSISTANT)
478 .setType(MetricsEvent.TYPE_OPEN)
479 .setSubtype(toLoggingSubType(invocationType, phoneState)));
480 }
481
482 protected final int toLoggingSubType(int invocationType, int phoneState) {
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400483 // Note that this logic will break if the number of Assistant invocation types exceeds 7.
484 // There are currently 5 invocation types, but we will be migrating to the new logging
485 // framework in the next update.
486 int subType = mHandleController.areHandlesShowing() ? 0 : 1;
487 subType |= invocationType << 1;
488 subType |= phoneState << 4;
489 return subType;
490 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700491}