blob: cf9c470dc04eaa30d98e75beec3e51b5aff3c7d0 [file] [log] [blame]
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001package com.android.systemui.assist;
2
Yohei Yukawa528e4682015-09-10 22:21:04 -07003import android.annotation.NonNull;
4import android.annotation.Nullable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07005import android.app.ActivityManager;
6import android.app.ActivityOptions;
7import android.app.SearchManager;
8import android.content.ActivityNotFoundException;
9import android.content.ComponentName;
10import android.content.Context;
11import android.content.Intent;
Jason Monk9c7844c2017-01-18 15:21:53 -050012import android.content.pm.ActivityInfo;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070013import android.content.pm.PackageManager;
Jason Monk9c7844c2017-01-18 15:21:53 -050014import android.content.res.Configuration;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070015import android.content.res.Resources;
16import android.graphics.PixelFormat;
Steven Wu11da5742019-04-25 16:12:06 -040017import android.metrics.LogMaker;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070018import android.os.AsyncTask;
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -080019import android.os.Binder;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070020import android.os.Bundle;
Xiyuan Xiae6de8b92015-06-06 22:18:05 -070021import android.os.Handler;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070022import android.os.RemoteException;
Govinda Wasserman27aa92b2019-04-16 14:45:54 -040023import android.os.SystemClock;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070024import android.os.UserHandle;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070025import android.provider.Settings;
Dianne Hackborn17f69352015-07-17 18:04:14 -070026import android.service.voice.VoiceInteractionSession;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070027import android.util.Log;
28import android.view.Gravity;
29import android.view.LayoutInflater;
30import android.view.View;
31import android.view.ViewGroup;
32import android.view.WindowManager;
33import android.widget.ImageView;
34
Adrian Roose9175082015-06-15 13:23:14 -070035import com.android.internal.app.AssistUtils;
Annie Chinecb9f3e2016-06-27 16:01:52 -070036import com.android.internal.app.IVoiceInteractionSessionListener;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070037import com.android.internal.app.IVoiceInteractionSessionShowCallback;
Steven Wu11da5742019-04-25 16:12:06 -040038import com.android.internal.logging.MetricsLogger;
39import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Kaori Katou70554e02016-08-04 17:11:07 +090040import com.android.keyguard.KeyguardUpdateMonitor;
Jason Monk9c7844c2017-01-18 15:21:53 -050041import com.android.settingslib.applications.InterestingConfigChanges;
42import com.android.systemui.ConfigurationChangedReceiver;
Miranda Kephart433c8112019-05-22 12:25:51 -040043import com.android.systemui.Dependency;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070044import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050045import com.android.systemui.SysUiServiceProvider;
Miranda Kephart433c8112019-05-22 12:25:51 -040046import com.android.systemui.assist.ui.DefaultUiController;
47import com.android.systemui.recents.OverviewProxyService;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070048import com.android.systemui.statusbar.CommandQueue;
Jason Monk9c7844c2017-01-18 15:21:53 -050049import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Adrian Roose9175082015-06-15 13:23:14 -070050
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070051/**
Selim Cineke70d6532015-04-24 16:46:13 -070052 * Class to manage everything related to assist in SystemUI.
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070053 */
Jason Monk9c7844c2017-01-18 15:21:53 -050054public class AssistManager implements ConfigurationChangedReceiver {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070055
Miranda Kephart433c8112019-05-22 12:25:51 -040056 /**
57 * Controls the UI for showing Assistant invocation progress.
58 */
59 public interface UiController {
60 /**
61 * Updates the invocation progress.
62 *
63 * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
64 * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
65 * INVOCATION_HOME_BUTTON_LONG_PRESS
66 * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
67 * gesture; 1 represents the end.
68 */
69 void onInvocationProgress(int type, float progress);
70
71 /**
72 * Called when an invocation gesture completes.
73 *
74 * @param velocity the speed of the invocation gesture, in pixels per millisecond. For
75 * drags, this is 0.
76 */
77 void onGestureCompletion(float velocity);
78
79 /**
80 * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints.
81 */
82 void processBundle(Bundle hints);
83
84 /**
James O'Leary7b92b122019-07-09 12:43:45 -040085 * Hides any SysUI for the assistant, but _does not_ close the assistant itself.
Miranda Kephart433c8112019-05-22 12:25:51 -040086 */
87 void hide();
88 }
89
Selim Cineke70d6532015-04-24 16:46:13 -070090 private static final String TAG = "AssistManager";
Matt Casey4cff16f2019-01-14 14:56:06 -050091
92 // Note that VERBOSE logging may leak PII (e.g. transcription contents).
93 private static final boolean VERBOSE = false;
94
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070095 private static final String ASSIST_ICON_METADATA_NAME =
96 "com.android.systemui.action_assist_icon";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -040097 private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
Govinda Wassermana2c887602019-05-08 08:02:47 -040098 private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
Govinda Wasserman27aa92b2019-04-16 14:45:54 -040099 public static final String INVOCATION_TYPE_KEY = "invocation_type";
100
101 public static final int INVOCATION_TYPE_GESTURE = 1;
102 public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
103 public static final int INVOCATION_TYPE_VOICE = 3;
104 public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
105 public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700106
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400107 public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
108 public static final int DISMISS_REASON_TAP = 2;
109 public static final int DISMISS_REASON_BACK = 3;
110 public static final int DISMISS_REASON_TIMEOUT = 4;
111
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700112 private static final long TIMEOUT_SERVICE = 2500;
113 private static final long TIMEOUT_ACTIVITY = 1000;
114
Annie Chin4c249ff2016-07-08 14:52:00 -0700115 protected final Context mContext;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700116 private final WindowManager mWindowManager;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700117 private final AssistDisclosure mAssistDisclosure;
Jason Monk9c7844c2017-01-18 15:21:53 -0500118 private final InterestingConfigChanges mInterestingConfigChanges;
Govinda Wassermana2c887602019-05-08 08:02:47 -0400119 private final PhoneStateMonitor mPhoneStateMonitor;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400120 private final AssistHandleBehaviorController mHandleController;
Miranda Kephart433c8112019-05-22 12:25:51 -0400121 private final UiController mUiController;
Adrian Roos4f43dc02015-06-17 16:43:38 -0700122
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700123 private AssistOrbContainer mView;
Jason Monk9c7844c2017-01-18 15:21:53 -0500124 private final DeviceProvisionedController mDeviceProvisionedController;
Annie Chinecb9f3e2016-06-27 16:01:52 -0700125 protected final AssistUtils mAssistUtils;
Rajeev Kumar3e084302017-09-25 19:08:12 -0700126 private final boolean mShouldEnableOrb;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700127
128 private IVoiceInteractionSessionShowCallback mShowCallback =
129 new IVoiceInteractionSessionShowCallback.Stub() {
130
Miranda Kephart433c8112019-05-22 12:25:51 -0400131 @Override
132 public void onFailed() throws RemoteException {
133 mView.post(mHideRunnable);
134 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700135
Miranda Kephart433c8112019-05-22 12:25:51 -0400136 @Override
137 public void onShown() throws RemoteException {
138 mView.post(mHideRunnable);
139 }
140 };
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700141
142 private Runnable mHideRunnable = new Runnable() {
143 @Override
144 public void run() {
145 mView.removeCallbacks(this);
146 mView.show(false /* show */, true /* animate */);
147 }
148 };
149
Jason Monk9c7844c2017-01-18 15:21:53 -0500150 public AssistManager(DeviceProvisionedController controller, Context context) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700151 mContext = context;
Jason Monk9c7844c2017-01-18 15:21:53 -0500152 mDeviceProvisionedController = controller;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700153 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Adrian Roose9175082015-06-15 13:23:14 -0700154 mAssistUtils = new AssistUtils(context);
Adrian Roos4f43dc02015-06-17 16:43:38 -0700155 mAssistDisclosure = new AssistDisclosure(context, new Handler());
Govinda Wassermana2c887602019-05-08 08:02:47 -0400156 mPhoneStateMonitor = new PhoneStateMonitor(context);
Govinda Wasserman5dfe9652019-05-30 13:24:24 -0400157 mHandleController =
158 new AssistHandleBehaviorController(context, mAssistUtils, new Handler());
Annie Chinecb9f3e2016-06-27 16:01:52 -0700159
160 registerVoiceInteractionSessionListener();
Jason Monk3edad312017-06-05 11:33:48 -0400161 mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
162 | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
163 | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
Jason Monk9c7844c2017-01-18 15:21:53 -0500164 onConfigurationChanged(context.getResources().getConfiguration());
Rajeev Kumar3e084302017-09-25 19:08:12 -0700165 mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
Miranda Kephart433c8112019-05-22 12:25:51 -0400166
167 mUiController = new DefaultUiController(mContext);
168
169 OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class);
170 overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() {
171 @Override
172 public void onAssistantProgress(float progress) {
173 // Progress goes from 0 to 1 to indicate how close the assist gesture is to
174 // completion.
175 onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
176 }
177
178 @Override
179 public void onAssistantGestureCompletion(float velocity) {
180 onGestureCompletion(velocity);
181 }
182 });
Annie Chinecb9f3e2016-06-27 16:01:52 -0700183 }
184
185 protected void registerVoiceInteractionSessionListener() {
186 mAssistUtils.registerVoiceInteractionSessionListener(
187 new IVoiceInteractionSessionListener.Stub() {
Matt Casey4cff16f2019-01-14 14:56:06 -0500188 @Override
189 public void onVoiceSessionShown() throws RemoteException {
190 if (VERBOSE) {
191 Log.v(TAG, "Voice open");
192 }
193 }
Annie Chinecb9f3e2016-06-27 16:01:52 -0700194
Matt Casey4cff16f2019-01-14 14:56:06 -0500195 @Override
196 public void onVoiceSessionHidden() throws RemoteException {
197 if (VERBOSE) {
198 Log.v(TAG, "Voice closed");
199 }
200 }
201
202 @Override
James O'Leary9c9dd982019-02-08 15:49:06 -0500203 public void onSetUiHints(Bundle hints) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500204 if (VERBOSE) {
James O'Leary9c9dd982019-02-08 15:49:06 -0500205 Log.v(TAG, "UI hints received");
Matt Casey4cff16f2019-01-14 14:56:06 -0500206 }
207 }
208 });
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700209 }
210
Jason Monk9c7844c2017-01-18 15:21:53 -0500211 public void onConfigurationChanged(Configuration newConfiguration) {
212 if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
213 return;
214 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700215 boolean visible = false;
216 if (mView != null) {
217 visible = mView.isShowing();
218 mWindowManager.removeView(mView);
219 }
220
221 mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
222 R.layout.assist_orb, null);
223 mView.setVisibility(View.GONE);
224 mView.setSystemUiVisibility(
225 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
226 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
227 WindowManager.LayoutParams lp = getLayoutParams();
228 mWindowManager.addView(mView, lp);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700229 if (visible) {
230 mView.show(true /* show */, false /* animate */);
231 }
232 }
233
Annie Chin937a9912016-05-31 10:14:23 -0700234 protected boolean shouldShowOrb() {
jschungfc5e15c2019-05-08 11:11:59 +0900235 return false;
Annie Chin937a9912016-05-31 10:14:23 -0700236 }
237
Jorim Jaggi165ce062015-07-06 16:18:11 -0700238 public void startAssist(Bundle args) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700239 final ComponentName assistComponent = getAssistInfo();
240 if (assistComponent == null) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700241 return;
242 }
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700243
Yohei Yukawa528e4682015-09-10 22:21:04 -0700244 final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
Annie Chin937a9912016-05-31 10:14:23 -0700245 if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
Yohei Yukawa528e4682015-09-10 22:21:04 -0700246 showOrb(assistComponent, isService);
Xiyuan Xiae6de8b92015-06-06 22:18:05 -0700247 mView.postDelayed(mHideRunnable, isService
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700248 ? TIMEOUT_SERVICE
249 : TIMEOUT_ACTIVITY);
250 }
Dan Sandler62bdce52019-04-23 19:18:21 -0400251
252 if (args == null) {
253 args = new Bundle();
254 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400255 int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
256 if (invocationType == INVOCATION_TYPE_GESTURE) {
257 mHandleController.onAssistantGesturePerformed();
258 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400259 int phoneState = mPhoneStateMonitor.getPhoneState();
260 args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState);
Govinda Wasserman6445e682019-06-04 09:37:32 -0400261 args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
Govinda Wasserman6418e972019-06-03 12:37:43 -0400262 logStartAssist(invocationType, phoneState);
Yohei Yukawa528e4682015-09-10 22:21:04 -0700263 startAssistInternal(args, assistComponent, isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700264 }
265
Govinda Wassermanb130e942019-04-15 10:07:37 -0400266 /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
267 public void onInvocationProgress(int type, float progress) {
Miranda Kephart433c8112019-05-22 12:25:51 -0400268 mUiController.onInvocationProgress(type, progress);
Govinda Wassermanb130e942019-04-15 10:07:37 -0400269 }
270
Miranda Kephart433c8112019-05-22 12:25:51 -0400271 /**
272 * Called when the user has invoked the assistant with the incoming velocity, in pixels per
Miranda Kephart4be26902019-05-17 13:55:37 -0400273 * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
274 * zero.
275 */
Miranda Kephart433c8112019-05-22 12:25:51 -0400276 public void onGestureCompletion(float velocity) {
277 mUiController.onGestureCompletion(velocity);
Miranda Kephart4be26902019-05-17 13:55:37 -0400278 }
279
Jorim Jaggib835dd72015-06-08 12:28:42 -0700280 public void hideAssist() {
Adrian Roose9175082015-06-15 13:23:14 -0700281 mAssistUtils.hideCurrentSession();
Jorim Jaggib835dd72015-06-08 12:28:42 -0700282 }
283
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700284 private WindowManager.LayoutParams getLayoutParams() {
285 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
286 ViewGroup.LayoutParams.MATCH_PARENT,
287 mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
288 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
289 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
290 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
291 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
292 PixelFormat.TRANSLUCENT);
Wale Ogunwale6ce0fb82016-12-13 14:24:00 -0800293 lp.token = new Binder();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700294 lp.gravity = Gravity.BOTTOM | Gravity.START;
295 lp.setTitle("AssistPreviewPanel");
296 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
297 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
298 return lp;
299 }
300
Yohei Yukawa528e4682015-09-10 22:21:04 -0700301 private void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
302 maybeSwapSearchIcon(assistComponent, isService);
Rajeev Kumar3e084302017-09-25 19:08:12 -0700303 if (mShouldEnableOrb) {
304 mView.show(true /* show */, true /* animate */);
305 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700306 }
307
Yohei Yukawa528e4682015-09-10 22:21:04 -0700308 private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent,
309 boolean isService) {
310 if (isService) {
311 startVoiceInteractor(args);
312 } else {
313 startAssistActivity(args, assistComponent);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700314 }
315 }
316
Yohei Yukawa528e4682015-09-10 22:21:04 -0700317 private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500318 if (!mDeviceProvisionedController.isDeviceProvisioned()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700319 return;
320 }
321
322 // Close Recent Apps if needed
Jason Monk9c7844c2017-01-18 15:21:53 -0500323 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).animateCollapsePanels(
Jason Monk297c04e2018-08-23 17:16:59 -0400324 CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
325 false /* force */);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700326
Adrian Roos4f43dc02015-06-17 16:43:38 -0700327 boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
328 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
329
Steven Wu2b71d792018-05-08 11:03:17 -0400330 final SearchManager searchManager =
Miranda Kephart433c8112019-05-22 12:25:51 -0400331 (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
Steven Wu2b71d792018-05-08 11:03:17 -0400332 if (searchManager == null) {
333 return;
334 }
335 final Intent intent = searchManager.getAssistIntent(structureEnabled);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700336 if (intent == null) {
337 return;
338 }
Yohei Yukawa528e4682015-09-10 22:21:04 -0700339 intent.setComponent(assistComponent);
Jorim Jaggi165ce062015-07-06 16:18:11 -0700340 intent.putExtras(args);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700341
Rajeev Kumarcd497ef2019-08-06 12:02:47 -0700342 if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) {
Adrian Roos4f43dc02015-06-17 16:43:38 -0700343 showDisclosure();
344 }
345
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700346 try {
347 final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
348 R.anim.search_launch_enter, R.anim.search_launch_exit);
349 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
350 AsyncTask.execute(new Runnable() {
351 @Override
352 public void run() {
353 mContext.startActivityAsUser(intent, opts.toBundle(),
354 new UserHandle(UserHandle.USER_CURRENT));
355 }
356 });
357 } catch (ActivityNotFoundException e) {
358 Log.w(TAG, "Activity not found for " + intent.getAction());
359 }
360 }
361
Jorim Jaggi165ce062015-07-06 16:18:11 -0700362 private void startVoiceInteractor(Bundle args) {
Dianne Hackborn17f69352015-07-17 18:04:14 -0700363 mAssistUtils.showSessionForActiveService(args,
364 VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700365 }
366
Selim Cineke70d6532015-04-24 16:46:13 -0700367 public void launchVoiceAssistFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700368 mAssistUtils.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700369 }
370
Selim Cineke70d6532015-04-24 16:46:13 -0700371 public boolean canVoiceAssistBeLaunchedFromKeyguard() {
Adrian Roose9175082015-06-15 13:23:14 -0700372 return mAssistUtils.activeServiceSupportsLaunchFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700373 }
374
375 public ComponentName getVoiceInteractorComponentName() {
Adrian Roose9175082015-06-15 13:23:14 -0700376 return mAssistUtils.getActiveServiceComponentName();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700377 }
378
379 private boolean isVoiceSessionRunning() {
Adrian Roose9175082015-06-15 13:23:14 -0700380 return mAssistUtils.isSessionRunning();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700381 }
382
Yohei Yukawa528e4682015-09-10 22:21:04 -0700383 private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
384 replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
385 isService);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700386 }
387
388 public void replaceDrawable(ImageView v, ComponentName component, String name,
389 boolean isService) {
390 if (component != null) {
391 try {
392 PackageManager packageManager = mContext.getPackageManager();
393 // Look for the search icon specified in the activity meta-data
394 Bundle metaData = isService
395 ? packageManager.getServiceInfo(
Miranda Kephart433c8112019-05-22 12:25:51 -0400396 component, PackageManager.GET_META_DATA).metaData
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700397 : packageManager.getActivityInfo(
398 component, PackageManager.GET_META_DATA).metaData;
399 if (metaData != null) {
400 int iconResId = metaData.getInt(name);
401 if (iconResId != 0) {
402 Resources res = packageManager.getResourcesForApplication(
403 component.getPackageName());
404 v.setImageDrawable(res.getDrawable(iconResId));
405 return;
406 }
407 }
408 } catch (PackageManager.NameNotFoundException e) {
Matt Casey4cff16f2019-01-14 14:56:06 -0500409 if (VERBOSE) {
410 Log.v(TAG, "Assistant component "
411 + component.flattenToShortString() + " not found");
412 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700413 } catch (Resources.NotFoundException nfe) {
414 Log.w(TAG, "Failed to swap drawable from "
415 + component.flattenToShortString(), nfe);
416 }
417 }
418 v.setImageDrawable(null);
419 }
420
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400421 protected AssistHandleBehaviorController getHandleBehaviorController() {
422 return mHandleController;
423 }
424
Yohei Yukawa528e4682015-09-10 22:21:04 -0700425 @Nullable
Matthew Ngadd4c392019-03-01 16:02:31 -0800426 public ComponentName getAssistInfoForUser(int userId) {
427 return mAssistUtils.getAssistComponentForUser(userId);
428 }
429
430 @Nullable
Yohei Yukawa528e4682015-09-10 22:21:04 -0700431 private ComponentName getAssistInfo() {
Matthew Ngadd4c392019-03-01 16:02:31 -0800432 return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700433 }
Adrian Roos4f43dc02015-06-17 16:43:38 -0700434
435 public void showDisclosure() {
436 mAssistDisclosure.postShow();
437 }
Selim Cinek9a634992015-06-23 01:10:07 -0400438
Jorim Jaggi19695d92015-07-20 15:51:40 -0700439 public void onLockscreenShown() {
440 mAssistUtils.onLockscreenShown();
441 }
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400442
Govinda Wassermane9ff1ff2019-07-31 15:26:33 -0400443 public long getAssistHandleShowAndGoRemainingDurationMs() {
444 return mHandleController.getShowAndGoRemainingTimeMs();
445 }
446
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400447 /** Returns the logging flags for the given Assistant invocation type. */
448 public int toLoggingSubType(int invocationType) {
449 return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
450 }
451
Govinda Wasserman6418e972019-06-03 12:37:43 -0400452 protected void logStartAssist(int invocationType, int phoneState) {
453 MetricsLogger.action(
454 new LogMaker(MetricsEvent.ASSISTANT)
455 .setType(MetricsEvent.TYPE_OPEN)
456 .setSubtype(toLoggingSubType(invocationType, phoneState)));
457 }
458
459 protected final int toLoggingSubType(int invocationType, int phoneState) {
Govinda Wassermanb7cd1622019-05-31 11:59:19 -0400460 // Note that this logic will break if the number of Assistant invocation types exceeds 7.
461 // There are currently 5 invocation types, but we will be migrating to the new logging
462 // framework in the next update.
463 int subType = mHandleController.areHandlesShowing() ? 0 : 1;
464 subType |= invocationType << 1;
465 subType |= phoneState << 4;
466 return subType;
467 }
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700468}