Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 1 | package com.android.systemui.assist; |
| 2 | |
Lucas Dupin | 8968f6a | 2019-08-09 17:41:15 -0700 | [diff] [blame] | 3 | import static com.android.systemui.DejankUtils.whitelistIpcs; |
| 4 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 5 | import android.annotation.NonNull; |
| 6 | import android.annotation.Nullable; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 7 | import android.app.ActivityManager; |
| 8 | import android.app.ActivityOptions; |
| 9 | import android.app.SearchManager; |
| 10 | import android.content.ActivityNotFoundException; |
| 11 | import android.content.ComponentName; |
| 12 | import android.content.Context; |
| 13 | import android.content.Intent; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 14 | import android.content.pm.ActivityInfo; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 15 | import android.content.pm.PackageManager; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 16 | import android.content.res.Configuration; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 17 | import android.content.res.Resources; |
| 18 | import android.graphics.PixelFormat; |
Steven Wu | 11da574 | 2019-04-25 16:12:06 -0400 | [diff] [blame] | 19 | import android.metrics.LogMaker; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 20 | import android.os.AsyncTask; |
Wale Ogunwale | 6ce0fb8 | 2016-12-13 14:24:00 -0800 | [diff] [blame] | 21 | import android.os.Binder; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 22 | import android.os.Bundle; |
Xiyuan Xia | e6de8b9 | 2015-06-06 22:18:05 -0700 | [diff] [blame] | 23 | import android.os.Handler; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 24 | import android.os.RemoteException; |
Govinda Wasserman | 27aa92b | 2019-04-16 14:45:54 -0400 | [diff] [blame] | 25 | import android.os.SystemClock; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 26 | import android.os.UserHandle; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 27 | import android.provider.Settings; |
Dianne Hackborn | 17f6935 | 2015-07-17 18:04:14 -0700 | [diff] [blame] | 28 | import android.service.voice.VoiceInteractionSession; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 29 | import android.util.Log; |
| 30 | import android.view.Gravity; |
| 31 | import android.view.LayoutInflater; |
| 32 | import android.view.View; |
| 33 | import android.view.ViewGroup; |
| 34 | import android.view.WindowManager; |
| 35 | import android.widget.ImageView; |
| 36 | |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 37 | import com.android.internal.app.AssistUtils; |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 38 | import com.android.internal.app.IVoiceInteractionSessionListener; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 39 | import com.android.internal.app.IVoiceInteractionSessionShowCallback; |
Steven Wu | 11da574 | 2019-04-25 16:12:06 -0400 | [diff] [blame] | 40 | import com.android.internal.logging.MetricsLogger; |
| 41 | import com.android.internal.logging.nano.MetricsProto.MetricsEvent; |
Kaori Katou | 70554e0 | 2016-08-04 17:11:07 +0900 | [diff] [blame] | 42 | import com.android.keyguard.KeyguardUpdateMonitor; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 43 | import com.android.settingslib.applications.InterestingConfigChanges; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 44 | import com.android.systemui.R; |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 45 | import com.android.systemui.assist.ui.DefaultUiController; |
| 46 | import com.android.systemui.recents.OverviewProxyService; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 47 | import com.android.systemui.statusbar.CommandQueue; |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 48 | import com.android.systemui.statusbar.policy.ConfigurationController; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 49 | import com.android.systemui.statusbar.policy.DeviceProvisionedController; |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 50 | |
Govinda Wasserman | 2e86fb6 | 2019-08-13 11:35:44 -0400 | [diff] [blame] | 51 | import javax.inject.Inject; |
| 52 | import javax.inject.Singleton; |
| 53 | |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 54 | /** |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 55 | * Class to manage everything related to assist in SystemUI. |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 56 | */ |
Govinda Wasserman | 2e86fb6 | 2019-08-13 11:35:44 -0400 | [diff] [blame] | 57 | @Singleton |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 58 | public class AssistManager { |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 59 | |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 60 | /** |
| 61 | * Controls the UI for showing Assistant invocation progress. |
| 62 | */ |
| 63 | public interface UiController { |
| 64 | /** |
| 65 | * Updates the invocation progress. |
| 66 | * |
| 67 | * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE, |
| 68 | * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR, |
| 69 | * INVOCATION_HOME_BUTTON_LONG_PRESS |
| 70 | * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the |
| 71 | * gesture; 1 represents the end. |
| 72 | */ |
| 73 | void onInvocationProgress(int type, float progress); |
| 74 | |
| 75 | /** |
| 76 | * Called when an invocation gesture completes. |
| 77 | * |
| 78 | * @param velocity the speed of the invocation gesture, in pixels per millisecond. For |
| 79 | * drags, this is 0. |
| 80 | */ |
| 81 | void onGestureCompletion(float velocity); |
| 82 | |
| 83 | /** |
| 84 | * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints. |
| 85 | */ |
| 86 | void processBundle(Bundle hints); |
| 87 | |
| 88 | /** |
James O'Leary | 7b92b12 | 2019-07-09 12:43:45 -0400 | [diff] [blame] | 89 | * Hides any SysUI for the assistant, but _does not_ close the assistant itself. |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 90 | */ |
| 91 | void hide(); |
| 92 | } |
| 93 | |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 94 | private static final String TAG = "AssistManager"; |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 95 | |
| 96 | // Note that VERBOSE logging may leak PII (e.g. transcription contents). |
| 97 | private static final boolean VERBOSE = false; |
| 98 | |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 99 | private static final String ASSIST_ICON_METADATA_NAME = |
| 100 | "com.android.systemui.action_assist_icon"; |
Govinda Wasserman | 27aa92b | 2019-04-16 14:45:54 -0400 | [diff] [blame] | 101 | private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms"; |
Govinda Wasserman | a2c88760 | 2019-05-08 08:02:47 -0400 | [diff] [blame] | 102 | private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state"; |
Govinda Wasserman | 27aa92b | 2019-04-16 14:45:54 -0400 | [diff] [blame] | 103 | public static final String INVOCATION_TYPE_KEY = "invocation_type"; |
Hyunyoung Song | 8f9d34c | 2019-08-30 14:47:43 -0700 | [diff] [blame] | 104 | protected static final String ACTION_KEY = "action"; |
| 105 | protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles"; |
Govinda Wasserman | 27aa92b | 2019-04-16 14:45:54 -0400 | [diff] [blame] | 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 Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 112 | |
Govinda Wasserman | b7cd162 | 2019-05-31 11:59:19 -0400 | [diff] [blame] | 113 | 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 Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 118 | private static final long TIMEOUT_SERVICE = 2500; |
| 119 | private static final long TIMEOUT_ACTIVITY = 1000; |
| 120 | |
Annie Chin | 4c249ff | 2016-07-08 14:52:00 -0700 | [diff] [blame] | 121 | protected final Context mContext; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 122 | private final WindowManager mWindowManager; |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 123 | private final AssistDisclosure mAssistDisclosure; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 124 | private final InterestingConfigChanges mInterestingConfigChanges; |
Govinda Wasserman | a2c88760 | 2019-05-08 08:02:47 -0400 | [diff] [blame] | 125 | private final PhoneStateMonitor mPhoneStateMonitor; |
Govinda Wasserman | c7495cd | 2019-05-20 14:43:28 -0400 | [diff] [blame] | 126 | private final AssistHandleBehaviorController mHandleController; |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 127 | private final UiController mUiController; |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 128 | |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 129 | private AssistOrbContainer mView; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 130 | private final DeviceProvisionedController mDeviceProvisionedController; |
Dave Mankoff | bcaca8a | 2019-10-31 18:04:08 -0400 | [diff] [blame] | 131 | private final CommandQueue mCommandQueue; |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 132 | protected final AssistUtils mAssistUtils; |
Rajeev Kumar | 3e08430 | 2017-09-25 19:08:12 -0700 | [diff] [blame] | 133 | private final boolean mShouldEnableOrb; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 134 | |
| 135 | private IVoiceInteractionSessionShowCallback mShowCallback = |
| 136 | new IVoiceInteractionSessionShowCallback.Stub() { |
| 137 | |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 138 | @Override |
| 139 | public void onFailed() throws RemoteException { |
| 140 | mView.post(mHideRunnable); |
| 141 | } |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 142 | |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 143 | @Override |
| 144 | public void onShown() throws RemoteException { |
| 145 | mView.post(mHideRunnable); |
| 146 | } |
| 147 | }; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 148 | |
| 149 | private Runnable mHideRunnable = new Runnable() { |
| 150 | @Override |
| 151 | public void run() { |
| 152 | mView.removeCallbacks(this); |
| 153 | mView.show(false /* show */, true /* animate */); |
| 154 | } |
| 155 | }; |
| 156 | |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 157 | private ConfigurationController.ConfigurationListener mConfigurationListener = |
| 158 | new ConfigurationController.ConfigurationListener() { |
| 159 | @Override |
| 160 | public void onConfigChanged(Configuration newConfig) { |
| 161 | if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { |
| 162 | return; |
| 163 | } |
| 164 | boolean visible = false; |
| 165 | if (mView != null) { |
| 166 | visible = mView.isShowing(); |
| 167 | mWindowManager.removeView(mView); |
| 168 | } |
| 169 | |
| 170 | mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate( |
| 171 | R.layout.assist_orb, null); |
| 172 | mView.setVisibility(View.GONE); |
| 173 | mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
| 174 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
| 175 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); |
| 176 | WindowManager.LayoutParams lp = getLayoutParams(); |
| 177 | mWindowManager.addView(mView, lp); |
| 178 | if (visible) { |
| 179 | mView.show(true /* show */, false /* animate */); |
| 180 | } |
| 181 | } |
| 182 | }; |
| 183 | |
Govinda Wasserman | 2e86fb6 | 2019-08-13 11:35:44 -0400 | [diff] [blame] | 184 | @Inject |
Govinda Wasserman | 61c92d6 | 2019-09-05 16:32:23 -0400 | [diff] [blame] | 185 | public AssistManager( |
| 186 | DeviceProvisionedController controller, |
| 187 | Context context, |
| 188 | AssistUtils assistUtils, |
Dave Mankoff | bcaca8a | 2019-10-31 18:04:08 -0400 | [diff] [blame] | 189 | AssistHandleBehaviorController handleController, |
Fabian Kozynski | 5ca7a51 | 2019-10-16 19:56:11 +0000 | [diff] [blame] | 190 | CommandQueue commandQueue, |
Dave Mankoff | 4dd47fa | 2019-11-07 10:44:48 -0500 | [diff] [blame] | 191 | PhoneStateMonitor phoneStateMonitor, |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 192 | OverviewProxyService overviewProxyService, |
| 193 | ConfigurationController configurationController) { |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 194 | mContext = context; |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 195 | mDeviceProvisionedController = controller; |
Dave Mankoff | bcaca8a | 2019-10-31 18:04:08 -0400 | [diff] [blame] | 196 | mCommandQueue = commandQueue; |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 197 | mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); |
Govinda Wasserman | 61c92d6 | 2019-09-05 16:32:23 -0400 | [diff] [blame] | 198 | mAssistUtils = assistUtils; |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 199 | mAssistDisclosure = new AssistDisclosure(context, new Handler()); |
Dave Mankoff | 4dd47fa | 2019-11-07 10:44:48 -0500 | [diff] [blame] | 200 | mPhoneStateMonitor = phoneStateMonitor; |
Govinda Wasserman | 61c92d6 | 2019-09-05 16:32:23 -0400 | [diff] [blame] | 201 | mHandleController = handleController; |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 202 | |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 203 | configurationController.addCallback(mConfigurationListener); |
| 204 | |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 205 | registerVoiceInteractionSessionListener(); |
Jason Monk | 3edad31 | 2017-06-05 11:33:48 -0400 | [diff] [blame] | 206 | mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION |
| 207 | | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE |
| 208 | | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS); |
Dave Mankoff | bba732d | 2019-11-20 13:04:54 -0500 | [diff] [blame] | 209 | mConfigurationListener.onConfigChanged(context.getResources().getConfiguration()); |
Rajeev Kumar | 3e08430 | 2017-09-25 19:08:12 -0700 | [diff] [blame] | 210 | mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic(); |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 211 | |
| 212 | mUiController = new DefaultUiController(mContext); |
| 213 | |
Dave Mankoff | 4dd47fa | 2019-11-07 10:44:48 -0500 | [diff] [blame] | 214 | overviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() { |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 215 | @Override |
| 216 | public void onAssistantProgress(float progress) { |
| 217 | // Progress goes from 0 to 1 to indicate how close the assist gesture is to |
| 218 | // completion. |
| 219 | onInvocationProgress(INVOCATION_TYPE_GESTURE, progress); |
| 220 | } |
| 221 | |
| 222 | @Override |
| 223 | public void onAssistantGestureCompletion(float velocity) { |
| 224 | onGestureCompletion(velocity); |
| 225 | } |
| 226 | }); |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 227 | } |
| 228 | |
| 229 | protected void registerVoiceInteractionSessionListener() { |
| 230 | mAssistUtils.registerVoiceInteractionSessionListener( |
| 231 | new IVoiceInteractionSessionListener.Stub() { |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 232 | @Override |
| 233 | public void onVoiceSessionShown() throws RemoteException { |
| 234 | if (VERBOSE) { |
| 235 | Log.v(TAG, "Voice open"); |
| 236 | } |
| 237 | } |
Annie Chin | ecb9f3e | 2016-06-27 16:01:52 -0700 | [diff] [blame] | 238 | |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 239 | @Override |
| 240 | public void onVoiceSessionHidden() throws RemoteException { |
| 241 | if (VERBOSE) { |
| 242 | Log.v(TAG, "Voice closed"); |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | @Override |
James O'Leary | 9c9dd98 | 2019-02-08 15:49:06 -0500 | [diff] [blame] | 247 | public void onSetUiHints(Bundle hints) { |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 248 | if (VERBOSE) { |
James O'Leary | 9c9dd98 | 2019-02-08 15:49:06 -0500 | [diff] [blame] | 249 | Log.v(TAG, "UI hints received"); |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 250 | } |
Hyunyoung Song | 8f9d34c | 2019-08-30 14:47:43 -0700 | [diff] [blame] | 251 | if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) { |
| 252 | requestAssistHandles(); |
| 253 | } |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 254 | } |
| 255 | }); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 256 | } |
| 257 | |
Annie Chin | 937a991 | 2016-05-31 10:14:23 -0700 | [diff] [blame] | 258 | protected boolean shouldShowOrb() { |
jschung | fc5e15c | 2019-05-08 11:11:59 +0900 | [diff] [blame] | 259 | return false; |
Annie Chin | 937a991 | 2016-05-31 10:14:23 -0700 | [diff] [blame] | 260 | } |
| 261 | |
Jorim Jaggi | 165ce06 | 2015-07-06 16:18:11 -0700 | [diff] [blame] | 262 | public void startAssist(Bundle args) { |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 263 | final ComponentName assistComponent = getAssistInfo(); |
| 264 | if (assistComponent == null) { |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 265 | return; |
| 266 | } |
Xiyuan Xia | e6de8b9 | 2015-06-06 22:18:05 -0700 | [diff] [blame] | 267 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 268 | final boolean isService = assistComponent.equals(getVoiceInteractorComponentName()); |
Annie Chin | 937a991 | 2016-05-31 10:14:23 -0700 | [diff] [blame] | 269 | if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) { |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 270 | showOrb(assistComponent, isService); |
Xiyuan Xia | e6de8b9 | 2015-06-06 22:18:05 -0700 | [diff] [blame] | 271 | mView.postDelayed(mHideRunnable, isService |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 272 | ? TIMEOUT_SERVICE |
| 273 | : TIMEOUT_ACTIVITY); |
| 274 | } |
Dan Sandler | 62bdce5 | 2019-04-23 19:18:21 -0400 | [diff] [blame] | 275 | |
| 276 | if (args == null) { |
| 277 | args = new Bundle(); |
| 278 | } |
Govinda Wasserman | 1f606b0 | 2019-05-29 09:16:02 -0400 | [diff] [blame] | 279 | int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0); |
| 280 | if (invocationType == INVOCATION_TYPE_GESTURE) { |
| 281 | mHandleController.onAssistantGesturePerformed(); |
| 282 | } |
Govinda Wasserman | b7cd162 | 2019-05-31 11:59:19 -0400 | [diff] [blame] | 283 | int phoneState = mPhoneStateMonitor.getPhoneState(); |
| 284 | args.putInt(INVOCATION_PHONE_STATE_KEY, phoneState); |
Govinda Wasserman | 6445e68 | 2019-06-04 09:37:32 -0400 | [diff] [blame] | 285 | args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime()); |
Govinda Wasserman | 6418e97 | 2019-06-03 12:37:43 -0400 | [diff] [blame] | 286 | logStartAssist(invocationType, phoneState); |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 287 | startAssistInternal(args, assistComponent, isService); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 288 | } |
| 289 | |
Govinda Wasserman | b130e94 | 2019-04-15 10:07:37 -0400 | [diff] [blame] | 290 | /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */ |
| 291 | public void onInvocationProgress(int type, float progress) { |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 292 | mUiController.onInvocationProgress(type, progress); |
Govinda Wasserman | b130e94 | 2019-04-15 10:07:37 -0400 | [diff] [blame] | 293 | } |
| 294 | |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 295 | /** |
| 296 | * Called when the user has invoked the assistant with the incoming velocity, in pixels per |
Miranda Kephart | 4be2690 | 2019-05-17 13:55:37 -0400 | [diff] [blame] | 297 | * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to |
| 298 | * zero. |
| 299 | */ |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 300 | public void onGestureCompletion(float velocity) { |
| 301 | mUiController.onGestureCompletion(velocity); |
Miranda Kephart | 4be2690 | 2019-05-17 13:55:37 -0400 | [diff] [blame] | 302 | } |
| 303 | |
Hyunyoung Song | 8f9d34c | 2019-08-30 14:47:43 -0700 | [diff] [blame] | 304 | protected void requestAssistHandles() { |
| 305 | mHandleController.onAssistHandlesRequested(); |
| 306 | } |
| 307 | |
Jorim Jaggi | b835dd7 | 2015-06-08 12:28:42 -0700 | [diff] [blame] | 308 | public void hideAssist() { |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 309 | mAssistUtils.hideCurrentSession(); |
Jorim Jaggi | b835dd7 | 2015-06-08 12:28:42 -0700 | [diff] [blame] | 310 | } |
| 311 | |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 312 | private WindowManager.LayoutParams getLayoutParams() { |
| 313 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams( |
| 314 | ViewGroup.LayoutParams.MATCH_PARENT, |
| 315 | mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height), |
| 316 | WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING, |
| 317 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
| 318 | | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
| 319 | | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, |
| 320 | PixelFormat.TRANSLUCENT); |
Wale Ogunwale | 6ce0fb8 | 2016-12-13 14:24:00 -0800 | [diff] [blame] | 321 | lp.token = new Binder(); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 322 | lp.gravity = Gravity.BOTTOM | Gravity.START; |
| 323 | lp.setTitle("AssistPreviewPanel"); |
| 324 | lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED |
| 325 | | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; |
| 326 | return lp; |
| 327 | } |
| 328 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 329 | private void showOrb(@NonNull ComponentName assistComponent, boolean isService) { |
| 330 | maybeSwapSearchIcon(assistComponent, isService); |
Rajeev Kumar | 3e08430 | 2017-09-25 19:08:12 -0700 | [diff] [blame] | 331 | if (mShouldEnableOrb) { |
| 332 | mView.show(true /* show */, true /* animate */); |
| 333 | } |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 334 | } |
| 335 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 336 | private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent, |
| 337 | boolean isService) { |
| 338 | if (isService) { |
| 339 | startVoiceInteractor(args); |
| 340 | } else { |
| 341 | startAssistActivity(args, assistComponent); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 342 | } |
| 343 | } |
| 344 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 345 | private void startAssistActivity(Bundle args, @NonNull ComponentName assistComponent) { |
Jason Monk | 9c7844c | 2017-01-18 15:21:53 -0500 | [diff] [blame] | 346 | if (!mDeviceProvisionedController.isDeviceProvisioned()) { |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 347 | return; |
| 348 | } |
| 349 | |
| 350 | // Close Recent Apps if needed |
Dave Mankoff | bcaca8a | 2019-10-31 18:04:08 -0400 | [diff] [blame] | 351 | mCommandQueue.animateCollapsePanels( |
Jason Monk | 297c04e | 2018-08-23 17:16:59 -0400 | [diff] [blame] | 352 | CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, |
| 353 | false /* force */); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 354 | |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 355 | boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), |
| 356 | Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0; |
| 357 | |
Steven Wu | 2b71d79 | 2018-05-08 11:03:17 -0400 | [diff] [blame] | 358 | final SearchManager searchManager = |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 359 | (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); |
Steven Wu | 2b71d79 | 2018-05-08 11:03:17 -0400 | [diff] [blame] | 360 | if (searchManager == null) { |
| 361 | return; |
| 362 | } |
| 363 | final Intent intent = searchManager.getAssistIntent(structureEnabled); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 364 | if (intent == null) { |
| 365 | return; |
| 366 | } |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 367 | intent.setComponent(assistComponent); |
Jorim Jaggi | 165ce06 | 2015-07-06 16:18:11 -0700 | [diff] [blame] | 368 | intent.putExtras(args); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 369 | |
Rajeev Kumar | cd497ef | 2019-08-06 12:02:47 -0700 | [diff] [blame] | 370 | if (structureEnabled && AssistUtils.isDisclosureEnabled(mContext)) { |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 371 | showDisclosure(); |
| 372 | } |
| 373 | |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 374 | try { |
| 375 | final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, |
| 376 | R.anim.search_launch_enter, R.anim.search_launch_exit); |
| 377 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| 378 | AsyncTask.execute(new Runnable() { |
| 379 | @Override |
| 380 | public void run() { |
| 381 | mContext.startActivityAsUser(intent, opts.toBundle(), |
| 382 | new UserHandle(UserHandle.USER_CURRENT)); |
| 383 | } |
| 384 | }); |
| 385 | } catch (ActivityNotFoundException e) { |
| 386 | Log.w(TAG, "Activity not found for " + intent.getAction()); |
| 387 | } |
| 388 | } |
| 389 | |
Jorim Jaggi | 165ce06 | 2015-07-06 16:18:11 -0700 | [diff] [blame] | 390 | private void startVoiceInteractor(Bundle args) { |
Dianne Hackborn | 17f6935 | 2015-07-17 18:04:14 -0700 | [diff] [blame] | 391 | mAssistUtils.showSessionForActiveService(args, |
| 392 | VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 393 | } |
| 394 | |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 395 | public void launchVoiceAssistFromKeyguard() { |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 396 | mAssistUtils.launchVoiceAssistFromKeyguard(); |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 397 | } |
| 398 | |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 399 | public boolean canVoiceAssistBeLaunchedFromKeyguard() { |
Lucas Dupin | 8968f6a | 2019-08-09 17:41:15 -0700 | [diff] [blame] | 400 | // TODO(b/140051519) |
| 401 | return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard()); |
Selim Cinek | e70d653 | 2015-04-24 16:46:13 -0700 | [diff] [blame] | 402 | } |
| 403 | |
| 404 | public ComponentName getVoiceInteractorComponentName() { |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 405 | return mAssistUtils.getActiveServiceComponentName(); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | private boolean isVoiceSessionRunning() { |
Adrian Roos | e917508 | 2015-06-15 13:23:14 -0700 | [diff] [blame] | 409 | return mAssistUtils.isSessionRunning(); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 410 | } |
| 411 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 412 | private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) { |
| 413 | replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME, |
| 414 | isService); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 415 | } |
| 416 | |
| 417 | public void replaceDrawable(ImageView v, ComponentName component, String name, |
| 418 | boolean isService) { |
| 419 | if (component != null) { |
| 420 | try { |
| 421 | PackageManager packageManager = mContext.getPackageManager(); |
| 422 | // Look for the search icon specified in the activity meta-data |
| 423 | Bundle metaData = isService |
| 424 | ? packageManager.getServiceInfo( |
Miranda Kephart | 433c811 | 2019-05-22 12:25:51 -0400 | [diff] [blame] | 425 | component, PackageManager.GET_META_DATA).metaData |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 426 | : packageManager.getActivityInfo( |
| 427 | component, PackageManager.GET_META_DATA).metaData; |
| 428 | if (metaData != null) { |
| 429 | int iconResId = metaData.getInt(name); |
| 430 | if (iconResId != 0) { |
| 431 | Resources res = packageManager.getResourcesForApplication( |
| 432 | component.getPackageName()); |
| 433 | v.setImageDrawable(res.getDrawable(iconResId)); |
| 434 | return; |
| 435 | } |
| 436 | } |
| 437 | } catch (PackageManager.NameNotFoundException e) { |
Matt Casey | 4cff16f | 2019-01-14 14:56:06 -0500 | [diff] [blame] | 438 | if (VERBOSE) { |
| 439 | Log.v(TAG, "Assistant component " |
| 440 | + component.flattenToShortString() + " not found"); |
| 441 | } |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 442 | } catch (Resources.NotFoundException nfe) { |
| 443 | Log.w(TAG, "Failed to swap drawable from " |
| 444 | + component.flattenToShortString(), nfe); |
| 445 | } |
| 446 | } |
| 447 | v.setImageDrawable(null); |
| 448 | } |
| 449 | |
Govinda Wasserman | c7495cd | 2019-05-20 14:43:28 -0400 | [diff] [blame] | 450 | protected AssistHandleBehaviorController getHandleBehaviorController() { |
| 451 | return mHandleController; |
| 452 | } |
| 453 | |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 454 | @Nullable |
Matthew Ng | add4c39 | 2019-03-01 16:02:31 -0800 | [diff] [blame] | 455 | public ComponentName getAssistInfoForUser(int userId) { |
| 456 | return mAssistUtils.getAssistComponentForUser(userId); |
| 457 | } |
| 458 | |
| 459 | @Nullable |
Yohei Yukawa | 528e468 | 2015-09-10 22:21:04 -0700 | [diff] [blame] | 460 | private ComponentName getAssistInfo() { |
Matthew Ng | add4c39 | 2019-03-01 16:02:31 -0800 | [diff] [blame] | 461 | return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser()); |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 462 | } |
Adrian Roos | 4f43dc0 | 2015-06-17 16:43:38 -0700 | [diff] [blame] | 463 | |
| 464 | public void showDisclosure() { |
| 465 | mAssistDisclosure.postShow(); |
| 466 | } |
Selim Cinek | 9a63499 | 2015-06-23 01:10:07 -0400 | [diff] [blame] | 467 | |
Jorim Jaggi | 19695d9 | 2015-07-20 15:51:40 -0700 | [diff] [blame] | 468 | public void onLockscreenShown() { |
Lucas Dupin | 8968f6a | 2019-08-09 17:41:15 -0700 | [diff] [blame] | 469 | // TODO(b/140052478) |
| 470 | whitelistIpcs(mAssistUtils::onLockscreenShown); |
Jorim Jaggi | 19695d9 | 2015-07-20 15:51:40 -0700 | [diff] [blame] | 471 | } |
Govinda Wasserman | b7cd162 | 2019-05-31 11:59:19 -0400 | [diff] [blame] | 472 | |
Govinda Wasserman | e9ff1ff | 2019-07-31 15:26:33 -0400 | [diff] [blame] | 473 | public long getAssistHandleShowAndGoRemainingDurationMs() { |
| 474 | return mHandleController.getShowAndGoRemainingTimeMs(); |
| 475 | } |
| 476 | |
Govinda Wasserman | b7cd162 | 2019-05-31 11:59:19 -0400 | [diff] [blame] | 477 | /** Returns the logging flags for the given Assistant invocation type. */ |
| 478 | public int toLoggingSubType(int invocationType) { |
| 479 | return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState()); |
| 480 | } |
| 481 | |
Govinda Wasserman | 6418e97 | 2019-06-03 12:37:43 -0400 | [diff] [blame] | 482 | protected void logStartAssist(int invocationType, int phoneState) { |
| 483 | MetricsLogger.action( |
| 484 | new LogMaker(MetricsEvent.ASSISTANT) |
| 485 | .setType(MetricsEvent.TYPE_OPEN) |
| 486 | .setSubtype(toLoggingSubType(invocationType, phoneState))); |
| 487 | } |
| 488 | |
| 489 | protected final int toLoggingSubType(int invocationType, int phoneState) { |
Govinda Wasserman | b7cd162 | 2019-05-31 11:59:19 -0400 | [diff] [blame] | 490 | // Note that this logic will break if the number of Assistant invocation types exceeds 7. |
| 491 | // There are currently 5 invocation types, but we will be migrating to the new logging |
| 492 | // framework in the next update. |
| 493 | int subType = mHandleController.areHandlesShowing() ? 0 : 1; |
| 494 | subType |= invocationType << 1; |
| 495 | subType |= phoneState << 4; |
| 496 | return subType; |
| 497 | } |
Jorim Jaggi | 2fdeeab | 2015-04-01 15:13:03 -0700 | [diff] [blame] | 498 | } |