blob: c4feac1d1a26497be8c863b8ef3809ccf1b2764f [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;
Jason Monk9c7844c2017-01-18 15:21:53 -050047import com.android.systemui.SysUiServiceProvider;
Miranda Kephart433c8112019-05-22 12:25:51 -040048import com.android.systemui.assist.ui.DefaultUiController;
49import 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";
106
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;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700131 protected final AssistUtils mAssistUtils;
Rajeev Kumar3e084302017-09-25 19:08:12 -0700132 private final boolean mShouldEnableOrb;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700133
134 private IVoiceInteractionSessionShowCallback mShowCallback =
135 new IVoiceInteractionSessionShowCallback.Stub() {
136
Miranda Kephart433c8112019-05-22 12:25:51 -0400137 @Override
138 public void onFailed() throws RemoteException {
139 mView.post(mHideRunnable);
140 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700141
Miranda Kephart433c8112019-05-22 12:25:51 -0400142 @Override
143 public void onShown() throws RemoteException {
144 mView.post(mHideRunnable);
145 }
146 };
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700147
148 private Runnable mHideRunnable = new Runnable() {
149 @Override
150 public void run() {
151 mView.removeCallbacks(this);
152 mView.show(false /* show */, true /* animate */);
153 }
154 };
155
Govinda Wasserman2e86fb62019-08-13 11:35:44 -0400156 @Inject
Jason Monk9c7844c2017-01-18 15:21:53 -0500157 public AssistManager(DeviceProvisionedController controller, Context context) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700158 mContext = context;
Jason Monk9c7844c2017-01-18 15:21:53 -0500159 mDeviceProvisionedController = controller;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700160 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Adrian Roose9175082015-06-15 13:23:14 -0700161 mAssistUtils = new AssistUtils(context);
Adrian Roos4f43dc02015-06-17 16:43:38 -0700162 mAssistDisclosure = new AssistDisclosure(context, new Handler());
Govinda Wassermana2c887602019-05-08 08:02:47 -0400163 mPhoneStateMonitor = new PhoneStateMonitor(context);
Govinda Wasserman5dfe9652019-05-30 13:24:24 -0400164 mHandleController =
165 new AssistHandleBehaviorController(context, mAssistUtils, new Handler());
Annie Chinecb9f3e2016-06-27 16:01:52 -0700166
167 registerVoiceInteractionSessionListener();
Jason Monk3edad312017-06-05 11:33:48 -0400168 mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
169 | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
170 | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
Jason Monk9c7844c2017-01-18 15:21:53 -0500171 onConfigurationChanged(context.getResources().getConfiguration());
Rajeev Kumar3e084302017-09-25 19:08:12 -0700172 mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
Miranda Kephart433c8112019-05-22 12:25:51 -0400173
174 mUiController = new DefaultUiController(mContext);
175
176 OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class);
177 overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() {
178 @Override
179 public void onAssistantProgress(float progress) {
180 // Progress goes from 0 to 1 to indicate how close the assist gesture is to
181 // completion.
182 onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
183 }
184
185 @Override
186 public void onAssistantGestureCompletion(float velocity) {
187 onGestureCompletion(velocity);
188 }
189 });
Annie Chinecb9f3e2016-06-27 16:01:52 -0700190 }
191
192 protected void registerVoiceInteractionSessionListener() {
193 mAssistUtils.registerVoiceInteractionSessionListener(
194 new IVoiceInteractionSessionListener.Stub() {
Matt Casey4cff16f2019-01-14 14:56:06 -0500195 @Override
196 public void onVoiceSessionShown() throws RemoteException {
197 if (VERBOSE) {
198 Log.v(TAG, "Voice open");
199 }
200 }
Annie Chinecb9f3e2016-06-27 16:01:52 -0700201
Matt Casey4cff16f2019-01-14 14:56:06 -0500202 @Override
203 public void onVoiceSessionHidden() throws RemoteException {
204 if (VERBOSE) {
205 Log.v(TAG, "Voice closed");
206 }
207 }
208
209 @Override
James O'Leary9c9dd982019-02-08 15:49:06 -0500210 public void onSetUiHints(Bundle hints) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500211 if (VERBOSE) {
James O'Leary9c9dd982019-02-08 15:49:06 -0500212 Log.v(TAG, "UI hints received");
Matt Casey4cff16f2019-01-14 14:56:06 -0500213 }
214 }
215 });
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700216 }
217
Jason Monk9c7844c2017-01-18 15:21:53 -0500218 public void onConfigurationChanged(Configuration newConfiguration) {
219 if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
220 return;
221 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700222 boolean visible = false;
223 if (mView != null) {
224 visible = mView.isShowing();
225 mWindowManager.removeView(mView);
226 }
227
228 mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
229 R.layout.assist_orb, null);
230 mView.setVisibility(View.GONE);
231 mView.setSystemUiVisibility(
232 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
233 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
234 WindowManager.LayoutParams lp = getLayoutParams();
235 mWindowManager.addView(mView, lp);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700236 if (visible) {
237 mView.show(true /* show */, false /* animate */);
238 }
239 }
240
Annie Chin937a9912016-05-31 10:14:23 -0700241 protected boolean shouldShowOrb() {
jschungfc5e15c2019-05-08 11:11:59 +0900242 return false;
Annie Chin937a9912016-05-31 10:14:23 -0700243 }
244
Jorim Jaggi165ce062015-07-06 16:18:11 -0700245 public void startAssist(Bundle args) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700246 final ComponentName assistComponent = getAssistInfo();
247 if (assistComponent == null) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700248 return;
249 }
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700250
Yohei Yukawa528e4682015-09-10 22:21:04 -0700251 final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
Annie Chin937a9912016-05-31 10:14:23 -0700252 if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700253 showOrb(assistComponent, isService);
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700254 mView.postDelayed(mHideRunnable, isService
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700255 ? TIMEOUT_SERVICE
256 : TIMEOUT_ACTIVITY);
257 }
Dan Sandler62bdce52019-04-23 19:18:21 -0400258
259 if (args == null) {
260 args = new Bundle();
261 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400262 int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
263 if (invocationType == INVOCATION_TYPE_GESTURE) {
264 mHandleController.onAssistantGesturePerformed();
265 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400266 int phoneState = mPhoneStateMonitor.getPhoneState();
267 args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
Govinda Wasserman6445e682019-06-04 09:37:32 -0400268 args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
Govinda Wasserman6418e972019-06-03 12:37:43 -0400269 logStartAssist(invocationType, phoneState);
Yohei Yukawa528e4682015-09-10 22:21:04 -0700270 startAssistInternal(args, assistComponent, isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700271 }
272
Govinda Wassermanb130e942019-04-15 10:07:37 -0400273 /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
274 public void onInvocationProgress(int type, float progress) {
Miranda Kephart433c8112019-05-22 12:25:51 -0400275 mUiController.onInvocationProgress(type, progress);
Govinda Wassermanb130e942019-04-15 10:07:37 -0400276 }
277
Miranda Kephart433c8112019-05-22 12:25:51 -0400278 /**
279 * Called when the user has invoked the assistant with the incoming velocity, in pixels per
Miranda Kephart4be26902019-05-17 13:55:37 -0400280 * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
281 * zero.
282 */
Miranda Kephart433c8112019-05-22 12:25:51 -0400283 public void onGestureCompletion(float velocity) {
284 mUiController.onGestureCompletion(velocity);
Miranda Kephart4be26902019-05-17 13:55:37 -0400285 }
286
Jorim Jaggib835dd72015-06-08 12:28:42 -0700287 public void hideAssist() {
Adrian Roose9175082015-06-15 13:23:14 -0700288 mAssistUtils.hideCurrentSession();
Jorim Jaggib835dd72015-06-08 12:28:42 -0700289 }
290
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700291 private WindowManager.LayoutParams getLayoutParams() {
292 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
293 ViewGroup.LayoutParams.MATCH_PARENT,
294 mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
295 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
296 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
297 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
298 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
299 PixelFormat.TRANSLUCENT);
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800300 lp.token = new Binder();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700301 lp.gravity = Gravity.BOTTOM | Gravity.START;
302 lp.setTitle("AssistPreviewPanel");
303 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
304 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
305 return lp;
306 }
307
Yohei Yukawa528e4682015-09-10 22:21:04 -0700308 private void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
309 maybeSwapSearchIcon(assistComponent, isService);
Rajeev Kumar3e084302017-09-25 19:08:12 -0700310 if (mShouldEnableOrb) {
311 mView.show(true /* show */, true /* animate */);
312 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700313 }
314
Yohei Yukawa528e4682015-09-10 22:21:04 -0700315 private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent,
316 boolean isService) {
317 if (isService) {
318 startVoiceInteractor(args);
319 } else {
320 startAssistActivity(args, assistComponent);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700321 }
322 }
323
Yohei Yukawa528e4682015-09-10 22:21:04 -0700324 private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500325 if (!mDeviceProvisionedController.isDeviceProvisioned()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700326 return;
327 }
328
329 // Close Recent Apps if needed
Jason Monk9c7844c2017-01-18 15:21:53 -0500330 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).animateCollapsePanels(
Jason Monk297c04e2018-08-23 17:16:59 -0400331 CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
332 false /* force */);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700333
Adrian Roos4f43dc02015-06-17 16:43:38 -0700334 boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
335 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
336
Steven Wu2b71d792018-05-08 11:03:17 -0400337 final SearchManager searchManager =
Miranda Kephart433c8112019-05-22 12:25:51 -0400338 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
Steven Wu2b71d792018-05-08 11:03:17 -0400339 if (searchManager == null) {
340 return;
341 }
342 final Intent intent = searchManager.getAssistIntent(structureEnabled);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700343 if (intent == null) {
344 return;
345 }
Yohei Yukawa528e4682015-09-10 22:21:04 -0700346 intent.setComponent(assistComponent);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700347 intent.putExtras(args);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700348
Rajeev Kumarcd497ef2019-08-06 12:02:47 -0700349 if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
Adrian Roos4f43dc02015-06-17 16:43:38 -0700350 showDisclosure();
351 }
352
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700353 try {
354 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
355 R.anim.search_launch_enter, R.anim.search_launch_exit);
356 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
357 AsyncTask.execute(new Runnable() {
358 @Override
359 public void run() {
360 mContext.startActivityAsUser(intent, opts.toBundle(),
361 new UserHandle(UserHandle.USER_CURRENT));
362 }
363 });
364 } catch (ActivityNotFoundException e) {
365 Log.w(TAG, "Activity not found for " + intent.getAction());
366 }
367 }
368
Jorim Jaggi165ce062015-07-06 16:18:11 -0700369 private void startVoiceInteractor(Bundle args) {
Dianne Hackborn17f69352015-07-17 18:04:14 -0700370 mAssistUtils.showSessionForActiveService(args,
371 VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700372 }
373
Selim Cineke70d6532015-04-24 16:46:13 -0700374 public void launchVoiceAssistFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700375 mAssistUtils.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700376 }
377
Selim Cineke70d6532015-04-24 16:46:13 -0700378 public boolean canVoiceAssistBeLaunchedFromKeyguard() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700379 // TODO(b/140051519)
380 return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard());
Selim Cineke70d6532015-04-24 16:46:13 -0700381 }
382
383 public ComponentName getVoiceInteractorComponentName() {
Adrian Roose9175082015-06-15 13:23:14 -0700384 return mAssistUtils.getActiveServiceComponentName();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700385 }
386
387 private boolean isVoiceSessionRunning() {
Adrian Roose9175082015-06-15 13:23:14 -0700388 return mAssistUtils.isSessionRunning();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700389 }
390
Yohei Yukawa528e4682015-09-10 22:21:04 -0700391 private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
392 replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
393 isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700394 }
395
396 public void replaceDrawable(ImageView v, ComponentName component, String name,
397 boolean isService) {
398 if (component != null) {
399 try {
400 PackageManager packageManager = mContext.getPackageManager();
401 // Look for the search icon specified in the activity meta-data
402 Bundle metaData = isService
403 ? packageManager.getServiceInfo(
Miranda Kephart433c8112019-05-22 12:25:51 -0400404 component, PackageManager.GET_META_DATA).metaData
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700405 : packageManager.getActivityInfo(
406 component, PackageManager.GET_META_DATA).metaData;
407 if (metaData != null) {
408 int iconResId = metaData.getInt(name);
409 if (iconResId != 0) {
410 Resources res = packageManager.getResourcesForApplication(
411 component.getPackageName());
412 v.setImageDrawable(res.getDrawable(iconResId));
413 return;
414 }
415 }
416 } catch (PackageManager.NameNotFoundException e) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500417 if (VERBOSE) {
418 Log.v(TAG, "Assistant component "
419 + component.flattenToShortString() + " not found");
420 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700421 } catch (Resources.NotFoundException nfe) {
422 Log.w(TAG, "Failed to swap drawable from "
423 + component.flattenToShortString(), nfe);
424 }
425 }
426 v.setImageDrawable(null);
427 }
428
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400429 protected AssistHandleBehaviorController getHandleBehaviorController() {
430 return mHandleController;
431 }
432
Yohei Yukawa528e4682015-09-10 22:21:04 -0700433 @Nullable
Matthew Ngadd4c392019-03-01 16:02:31 -0800434 public ComponentName getAssistInfoForUser(int userId) {
435 return mAssistUtils.getAssistComponentForUser(userId);
436 }
437
438 @Nullable
Yohei Yukawa528e4682015-09-10 22:21:04 -0700439 private ComponentName getAssistInfo() {
Matthew Ngadd4c392019-03-01 16:02:31 -0800440 return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700441 }
Adrian Roos4f43dc02015-06-17 16:43:38 -0700442
443 public void showDisclosure() {
444 mAssistDisclosure.postShow();
445 }
Selim Cinek9a634992015-06-23 01:10:07 -0400446
Jorim Jaggi19695d92015-07-20 15:51:40 -0700447 public void onLockscreenShown() {
Lucas Dupin8968f6a2019-08-09 17:41:15 -0700448 // TODO(b/140052478)
449 whitelistIpcs(mAssistUtils::onLockscreenShown);
Jorim Jaggi19695d92015-07-20 15:51:40 -0700450 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400451
Govinda Wassermane9ff1ff2019-07-31 15:26:33 -0400452 public long getAssistHandleShowAndGoRemainingDurationMs() {
453 return mHandleController.getShowAndGoRemainingTimeMs();
454 }
455
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400456 /** Returns the logging flags for the given Assistant invocation type. */
457 public int toLoggingSubType(int invocationType) {
458 return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
459 }
460
Govinda Wasserman6418e972019-06-03 12:37:43 -0400461 protected void logStartAssist(int invocationType, int phoneState) {
462 MetricsLogger.action(
463 new LogMaker(MetricsEvent.ASSISTANT)
464 .setType(MetricsEvent.TYPE_OPEN)
465 .setSubtype(toLoggingSubType(invocationType, phoneState)));
466 }
467
468 protected final int toLoggingSubType(int invocationType, int phoneState) {
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400469 // Note that this logic will break if the number of Assistant invocation types exceeds 7.
470 // There are currently 5 invocation types, but we will be migrating to the new logging
471 // framework in the next update.
472 int subType = mHandleController.areHandlesShowing() ? 0 : 1;
473 subType |= invocationType << 1;
474 subType |= phoneState << 4;
475 return subType;
476 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700477}