1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.quickstep;
17 
18 import static android.content.Intent.ACTION_CHOOSER;
19 import static android.view.MotionEvent.ACTION_CANCEL;
20 import static android.view.MotionEvent.ACTION_DOWN;
21 import static android.view.MotionEvent.ACTION_UP;
22 
23 import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
24 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
25 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
26 import static com.android.quickstep.GestureState.DEFAULT_STATE;
27 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
28 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS;
29 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
30 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
31 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
32 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
33 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
34 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER;
35 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
36 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
37 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
38 
39 import android.annotation.TargetApi;
40 import android.app.ActivityManager;
41 import android.app.PendingIntent;
42 import android.app.RemoteAction;
43 import android.app.Service;
44 import android.content.ComponentName;
45 import android.content.Intent;
46 import android.content.SharedPreferences;
47 import android.content.res.Configuration;
48 import android.graphics.Point;
49 import android.graphics.Rect;
50 import android.graphics.Region;
51 import android.graphics.drawable.Icon;
52 import android.hardware.display.DisplayManager;
53 import android.os.Build;
54 import android.os.Bundle;
55 import android.os.IBinder;
56 import android.os.Looper;
57 import android.os.SystemClock;
58 import android.os.SystemProperties;
59 import android.util.Log;
60 import android.view.Choreographer;
61 import android.view.Display;
62 import android.view.InputEvent;
63 import android.view.MotionEvent;
64 import android.view.Surface;
65 import android.view.accessibility.AccessibilityManager;
66 
67 import androidx.annotation.BinderThread;
68 import androidx.annotation.NonNull;
69 import androidx.annotation.Nullable;
70 import androidx.annotation.UiThread;
71 
72 import com.android.launcher3.BaseDraggingActivity;
73 import com.android.launcher3.R;
74 import com.android.launcher3.ResourceUtils;
75 import com.android.launcher3.Utilities;
76 import com.android.launcher3.config.FeatureFlags;
77 import com.android.launcher3.provider.RestoreDbTask;
78 import com.android.launcher3.statemanager.StatefulActivity;
79 import com.android.launcher3.taskbar.TaskbarManager;
80 import com.android.launcher3.testing.TestLogging;
81 import com.android.launcher3.testing.TestProtocol;
82 import com.android.launcher3.tracing.LauncherTraceProto;
83 import com.android.launcher3.tracing.TouchInteractionServiceProto;
84 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
85 import com.android.launcher3.util.OnboardingPrefs;
86 import com.android.launcher3.util.TraceHelper;
87 import com.android.launcher3.util.WindowBounds;
88 import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
89 import com.android.quickstep.inputconsumers.AssistantInputConsumer;
90 import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
91 import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
92 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
93 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
94 import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
95 import com.android.quickstep.inputconsumers.ProgressDelegateInputConsumer;
96 import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
97 import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
98 import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
99 import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
100 import com.android.quickstep.util.ActiveGestureLog;
101 import com.android.quickstep.util.AssistantUtilities;
102 import com.android.quickstep.util.LauncherSplitScreenListener;
103 import com.android.quickstep.util.ProtoTracer;
104 import com.android.quickstep.util.ProxyScreenStatusProvider;
105 import com.android.quickstep.util.SplitScreenBounds;
106 import com.android.systemui.shared.recents.IOverviewProxy;
107 import com.android.systemui.shared.recents.ISystemUiProxy;
108 import com.android.systemui.shared.system.ActivityManagerWrapper;
109 import com.android.systemui.shared.system.InputChannelCompat;
110 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
111 import com.android.systemui.shared.system.InputConsumerController;
112 import com.android.systemui.shared.system.InputMonitorCompat;
113 import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController;
114 import com.android.systemui.shared.tracing.ProtoTraceable;
115 import com.android.wm.shell.onehanded.IOneHanded;
116 import com.android.wm.shell.pip.IPip;
117 import com.android.wm.shell.recents.IRecentTasks;
118 import com.android.wm.shell.splitscreen.ISplitScreen;
119 import com.android.wm.shell.startingsurface.IStartingWindow;
120 import com.android.wm.shell.transition.IShellTransitions;
121 
122 import java.io.FileDescriptor;
123 import java.io.PrintWriter;
124 import java.util.Arrays;
125 import java.util.LinkedList;
126 import java.util.function.Function;
127 
128 /**
129  * Service connected by system-UI for handling touch interaction.
130  */
131 @TargetApi(Build.VERSION_CODES.R)
132 public class TouchInteractionService extends Service
133         implements ProtoTraceable<LauncherTraceProto.Builder> {
134 
135     private static final String TAG = "TouchInteractionService";
136 
137     private static final String KEY_BACK_NOTIFICATION_COUNT = "backNotificationCount";
138     private static final String NOTIFY_ACTION_BACK = "com.android.quickstep.action.BACK_GESTURE";
139     private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once";
140     private static final int MAX_BACK_NOTIFICATION_COUNT = 3;
141 
142     /**
143      * System Action ID to show all apps.
144      * TODO: Use AccessibilityService's corresponding global action constant in S
145      */
146     private static final int SYSTEM_ACTION_ID_ALL_APPS = 14;
147 
148     public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
149             SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
150 
151     private int mBackGestureNotificationCounter = -1;
152 
153     private final TISBinder mTISBinder = new TISBinder();
154 
155     /**
156      * Local IOverviewProxy implementation with some methods for local components
157      */
158     public class TISBinder extends IOverviewProxy.Stub {
159 
160         @BinderThread
onInitialize(Bundle bundle)161         public void onInitialize(Bundle bundle) {
162             ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
163                     bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
164             IPip pip = IPip.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_PIP));
165             ISplitScreen splitscreen = ISplitScreen.Stub.asInterface(bundle.getBinder(
166                     KEY_EXTRA_SHELL_SPLIT_SCREEN));
167             IOneHanded onehanded = IOneHanded.Stub.asInterface(
168                     bundle.getBinder(KEY_EXTRA_SHELL_ONE_HANDED));
169             IShellTransitions shellTransitions = IShellTransitions.Stub.asInterface(
170                     bundle.getBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS));
171             IStartingWindow startingWindow = IStartingWindow.Stub.asInterface(
172                     bundle.getBinder(KEY_EXTRA_SHELL_STARTING_WINDOW));
173             ISmartspaceTransitionController smartspaceTransitionController =
174                     ISmartspaceTransitionController.Stub.asInterface(
175                             bundle.getBinder(KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER));
176             IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
177                     bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
178             MAIN_EXECUTOR.execute(() -> {
179                 SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
180                         splitscreen, onehanded, shellTransitions, startingWindow, recentTasks,
181                         smartspaceTransitionController);
182                 TouchInteractionService.this.initInputMonitor();
183                 preloadOverview(true /* fromInit */);
184             });
185             sIsInitialized = true;
186         }
187 
188         @BinderThread
onOverviewToggle()189         public void onOverviewToggle() {
190             TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
191             // If currently screen pinning, do not enter overview
192             if (mDeviceState.isScreenPinningActive()) {
193                 return;
194             }
195             TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
196             mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_TOGGLE);
197         }
198 
199         @BinderThread
200         @Override
onOverviewShown(boolean triggeredFromAltTab)201         public void onOverviewShown(boolean triggeredFromAltTab) {
202             if (triggeredFromAltTab) {
203                 TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
204                 mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_SHOW_NEXT_FOCUS);
205             } else {
206                 mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_SHOW);
207             }
208         }
209 
210         @BinderThread
211         @Override
onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey)212         public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
213             if (triggeredFromAltTab && !triggeredFromHomeKey) {
214                 // onOverviewShownFromAltTab hides the overview and ends at the target app
215                 mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_HIDE);
216             }
217         }
218 
219         @BinderThread
220         @Override
onTip(int actionType, int viewType)221         public void onTip(int actionType, int viewType) {
222             // Please delete this method from the interface
223         }
224 
225         @BinderThread
226         @Override
onAssistantAvailable(boolean available)227         public void onAssistantAvailable(boolean available) {
228             MAIN_EXECUTOR.execute(() -> {
229                 mDeviceState.setAssistantAvailable(available);
230                 TouchInteractionService.this.onAssistantVisibilityChanged();
231             });
232         }
233 
234         @BinderThread
235         @Override
onAssistantVisibilityChanged(float visibility)236         public void onAssistantVisibilityChanged(float visibility) {
237             MAIN_EXECUTOR.execute(() -> {
238                 mDeviceState.setAssistantVisibility(visibility);
239                 TouchInteractionService.this.onAssistantVisibilityChanged();
240             });
241         }
242 
243         @BinderThread
onBackAction(boolean completed, int downX, int downY, boolean isButton, boolean gestureSwipeLeft)244         public void onBackAction(boolean completed, int downX, int downY, boolean isButton,
245                 boolean gestureSwipeLeft) {
246             // Remove this method from the interface
247         }
248 
249         @BinderThread
onSystemUiStateChanged(int stateFlags)250         public void onSystemUiStateChanged(int stateFlags) {
251             MAIN_EXECUTOR.execute(() -> {
252                 int lastFlags = mDeviceState.getSystemUiStateFlags();
253                 mDeviceState.setSystemUiFlags(stateFlags);
254                 TouchInteractionService.this.onSystemUiFlagsChanged(lastFlags);
255             });
256         }
257 
258         @BinderThread
onActiveNavBarRegionChanges(Region region)259         public void onActiveNavBarRegionChanges(Region region) {
260             MAIN_EXECUTOR.execute(() -> mDeviceState.setDeferredGestureRegion(region));
261         }
262 
263         @Override
onSplitScreenSecondaryBoundsChanged(Rect bounds, Rect insets)264         public void onSplitScreenSecondaryBoundsChanged(Rect bounds, Rect insets) {
265             WindowBounds wb = new WindowBounds(bounds, insets);
266             MAIN_EXECUTOR.execute(() -> SplitScreenBounds.INSTANCE.setSecondaryWindowBounds(wb));
267         }
268 
269         @BinderThread
270         @Override
onScreenTurnedOn()271         public void onScreenTurnedOn() {
272             MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurnedOn);
273         }
274 
275         @Override
onRotationProposal(int rotation, boolean isValid)276         public void onRotationProposal(int rotation, boolean isValid) {
277             executeForTaskbarManager(() -> mTaskbarManager.onRotationProposal(rotation, isValid));
278         }
279 
280         @Override
disable(int displayId, int state1, int state2, boolean animate)281         public void disable(int displayId, int state1, int state2, boolean animate) {
282             executeForTaskbarManager(() -> mTaskbarManager
283                     .disableNavBarElements(displayId, state1, state2, animate));
284         }
285 
286         @Override
onSystemBarAttributesChanged(int displayId, int behavior)287         public void onSystemBarAttributesChanged(int displayId, int behavior) {
288             executeForTaskbarManager(() -> mTaskbarManager
289                     .onSystemBarAttributesChanged(displayId, behavior));
290         }
291 
292         @Override
onNavButtonsDarkIntensityChanged(float darkIntensity)293         public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
294             executeForTaskbarManager(() -> mTaskbarManager
295                     .onNavButtonsDarkIntensityChanged(darkIntensity));
296         }
297 
executeForTaskbarManager(final Runnable r)298         private void executeForTaskbarManager(final Runnable r) {
299             MAIN_EXECUTOR.execute(() -> {
300                 if (mTaskbarManager == null) {
301                     return;
302                 }
303                 r.run();
304             });
305         }
306 
getTaskbarManager()307         public TaskbarManager getTaskbarManager() {
308             return mTaskbarManager;
309         }
310 
getOverviewCommandHelper()311         public OverviewCommandHelper getOverviewCommandHelper() {
312             return mOverviewCommandHelper;
313         }
314 
315         /**
316          * Sets a proxy to bypass swipe up behavior
317          */
setSwipeUpProxy(Function<GestureState, AnimatedFloat> proxy)318         public void setSwipeUpProxy(Function<GestureState, AnimatedFloat> proxy) {
319             mSwipeUpProxyProvider = proxy != null ? proxy : (i -> null);
320         }
321     }
322 
323     private static boolean sConnected = false;
324     private static boolean sIsInitialized = false;
325     private RotationTouchHelper mRotationTouchHelper;
326 
isConnected()327     public static boolean isConnected() {
328         return sConnected;
329     }
330 
isInitialized()331     public static boolean isInitialized() {
332         return sIsInitialized;
333     }
334 
335     private final AbsSwipeUpHandler.Factory mLauncherSwipeHandlerFactory =
336             this::createLauncherSwipeHandler;
337     private final AbsSwipeUpHandler.Factory mFallbackSwipeHandlerFactory =
338             this::createFallbackSwipeHandler;
339 
340     private ActivityManagerWrapper mAM;
341     private OverviewCommandHelper mOverviewCommandHelper;
342     private OverviewComponentObserver mOverviewComponentObserver;
343     private InputConsumerController mInputConsumer;
344     private RecentsAnimationDeviceState mDeviceState;
345     private TaskAnimationManager mTaskAnimationManager;
346 
347     private @NonNull InputConsumer mUncheckedConsumer = InputConsumer.NO_OP;
348     private @NonNull InputConsumer mConsumer = InputConsumer.NO_OP;
349     private Choreographer mMainChoreographer;
350     private @Nullable ResetGestureInputConsumer mResetGestureInputConsumer;
351     private GestureState mGestureState = DEFAULT_STATE;
352 
353     private InputMonitorCompat mInputMonitorCompat;
354     private InputEventReceiver mInputEventReceiver;
355 
356     private DisplayManager mDisplayManager;
357 
358     private TaskbarManager mTaskbarManager;
359     private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
360 
361     @Override
onCreate()362     public void onCreate() {
363         super.onCreate();
364         // Initialize anything here that is needed in direct boot mode.
365         // Everything else should be initialized in onUserUnlocked() below.
366         mMainChoreographer = Choreographer.getInstance();
367         mAM = ActivityManagerWrapper.getInstance();
368         mDeviceState = new RecentsAnimationDeviceState(this, true);
369         mDisplayManager = getSystemService(DisplayManager.class);
370         mTaskbarManager = new TaskbarManager(this);
371         mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
372 
373         // Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
374         mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
375         mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
376         mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
377         mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
378 
379         ProtoTracer.INSTANCE.get(this).add(this);
380         LauncherSplitScreenListener.INSTANCE.get(this).init();
381         sConnected = true;
382     }
383 
disposeEventHandlers()384     private void disposeEventHandlers() {
385         if (mInputEventReceiver != null) {
386             mInputEventReceiver.dispose();
387             mInputEventReceiver = null;
388         }
389         if (mInputMonitorCompat != null) {
390             mInputMonitorCompat.dispose();
391             mInputMonitorCompat = null;
392         }
393     }
394 
initInputMonitor()395     private void initInputMonitor() {
396         disposeEventHandlers();
397 
398         if (mDeviceState.isButtonNavMode()) {
399             return;
400         }
401 
402         mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
403         mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
404                 mMainChoreographer, this::onInputEvent);
405 
406         mRotationTouchHelper.updateGestureTouchRegions();
407     }
408 
409     /**
410      * Called when the navigation mode changes, guaranteed to be after the device state has updated.
411      */
onNavigationModeChanged(SysUINavigationMode.Mode mode)412     private void onNavigationModeChanged(SysUINavigationMode.Mode mode) {
413         initInputMonitor();
414         resetHomeBounceSeenOnQuickstepEnabledFirstTime();
415     }
416 
417     /**
418      * Called when the one handed mode overlay package changes, to recreate touch region.
419      */
onOneHandedModeOverlayChanged(int newGesturalHeight)420     private void onOneHandedModeOverlayChanged(int newGesturalHeight) {
421         initInputMonitor();
422     }
423 
424     @UiThread
onUserUnlocked()425     public void onUserUnlocked() {
426         mTaskAnimationManager = new TaskAnimationManager(this);
427         mOverviewComponentObserver = new OverviewComponentObserver(this, mDeviceState);
428         mOverviewCommandHelper = new OverviewCommandHelper(this,
429                 mOverviewComponentObserver, mTaskAnimationManager);
430         mResetGestureInputConsumer = new ResetGestureInputConsumer(mTaskAnimationManager);
431         mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
432         mInputConsumer.registerInputConsumer();
433         onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
434         onAssistantVisibilityChanged();
435 
436         // Temporarily disable model preload
437         // new ModelPreload().start(this);
438         mBackGestureNotificationCounter = Math.max(0, Utilities.getDevicePrefs(this)
439                 .getInt(KEY_BACK_NOTIFICATION_COUNT, MAX_BACK_NOTIFICATION_COUNT));
440         resetHomeBounceSeenOnQuickstepEnabledFirstTime();
441 
442         mOverviewComponentObserver.setOverviewChangeListener(this::onOverviewTargetChange);
443         onOverviewTargetChange(mOverviewComponentObserver.isHomeAndOverviewSame());
444     }
445 
getOverviewCommandHelper()446     public OverviewCommandHelper getOverviewCommandHelper() {
447         return mOverviewCommandHelper;
448     }
449 
resetHomeBounceSeenOnQuickstepEnabledFirstTime()450     private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
451         if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
452             // Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
453             // mode doesn't have gestures
454             return;
455         }
456 
457         // Reset home bounce seen on quick step enabled for first time
458         SharedPreferences sharedPrefs = Utilities.getPrefs(this);
459         if (!sharedPrefs.getBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)) {
460             sharedPrefs.edit()
461                     .putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
462                     .putBoolean(OnboardingPrefs.HOME_BOUNCE_SEEN, false)
463                     .apply();
464         }
465     }
466 
onOverviewTargetChange(boolean isHomeAndOverviewSame)467     private void onOverviewTargetChange(boolean isHomeAndOverviewSame) {
468         AccessibilityManager am = getSystemService(AccessibilityManager.class);
469 
470         if (isHomeAndOverviewSame) {
471             Intent intent = new Intent(mOverviewComponentObserver.getHomeIntent())
472                     .setAction(Intent.ACTION_ALL_APPS);
473             RemoteAction allAppsAction = new RemoteAction(
474                     Icon.createWithResource(this, R.drawable.ic_apps),
475                     getString(R.string.all_apps_label),
476                     getString(R.string.all_apps_label),
477                     PendingIntent.getActivity(this, SYSTEM_ACTION_ID_ALL_APPS, intent,
478                             PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
479             am.registerSystemAction(allAppsAction, SYSTEM_ACTION_ID_ALL_APPS);
480         } else {
481             am.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
482         }
483 
484         StatefulActivity newOverviewActivity = mOverviewComponentObserver.getActivityInterface()
485                 .getCreatedActivity();
486         if (newOverviewActivity != null) {
487             mTaskbarManager.setActivity(newOverviewActivity);
488         }
489     }
490 
491     @UiThread
onSystemUiFlagsChanged(int lastSysUIFlags)492     private void onSystemUiFlagsChanged(int lastSysUIFlags) {
493         if (mDeviceState.isUserUnlocked()) {
494             int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
495             SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
496             mOverviewComponentObserver.onSystemUiStateChanged();
497             mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
498 
499             boolean wasExpanded = (lastSysUIFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
500             boolean isExpanded =
501                     (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
502             if (wasExpanded != isExpanded && isExpanded) {
503                 // End live tile when expanding the notification panel for the first time from
504                 // overview.
505                 mTaskAnimationManager.endLiveTile();
506             }
507 
508             if ((lastSysUIFlags & SYSUI_STATE_TRACING_ENABLED) !=
509                     (systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED)) {
510                 // Update the tracing state
511                 if ((systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED) != 0) {
512                     Log.d(TAG, "Starting tracing.");
513                     ProtoTracer.INSTANCE.get(this).start();
514                 } else {
515                     Log.d(TAG, "Stopping tracing. Dumping to file="
516                             + ProtoTracer.INSTANCE.get(this).getTraceFile());
517                     ProtoTracer.INSTANCE.get(this).stop();
518                 }
519             }
520         }
521     }
522 
523     @UiThread
onAssistantVisibilityChanged()524     private void onAssistantVisibilityChanged() {
525         if (mDeviceState.isUserUnlocked()) {
526             mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
527                     mDeviceState.getAssistantVisibility());
528         }
529     }
530 
531     @Override
onDestroy()532     public void onDestroy() {
533         Log.d(TAG, "Touch service destroyed: user=" + getUserId());
534         sIsInitialized = false;
535         if (mDeviceState.isUserUnlocked()) {
536             mInputConsumer.unregisterInputConsumer();
537             mOverviewComponentObserver.onDestroy();
538         }
539         disposeEventHandlers();
540         mDeviceState.destroy();
541         SystemUiProxy.INSTANCE.get(this).clearProxy();
542         ProtoTracer.INSTANCE.get(this).stop();
543         ProtoTracer.INSTANCE.get(this).remove(this);
544 
545         getSystemService(AccessibilityManager.class)
546                 .unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
547 
548         LauncherSplitScreenListener.INSTANCE.get(this).destroy();
549         mTaskbarManager.destroy();
550         sConnected = false;
551         super.onDestroy();
552     }
553 
554     @Override
onBind(Intent intent)555     public IBinder onBind(Intent intent) {
556         Log.d(TAG, "Touch service connected: user=" + getUserId());
557         return mTISBinder;
558     }
559 
onInputEvent(InputEvent ev)560     private void onInputEvent(InputEvent ev) {
561         if (!(ev instanceof MotionEvent)) {
562             Log.e(TAG, "Unknown event " + ev);
563             return;
564         }
565         MotionEvent event = (MotionEvent) ev;
566         if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
567             final Display display = mDisplayManager.getDisplay(mDeviceState.getDisplayId());
568             int rotation = display.getRotation();
569             Point sz = new Point();
570             display.getRealSize(sz);
571             if (rotation != Surface.ROTATION_0) {
572                 event.transform(InputChannelCompat.createRotationMatrix(rotation, sz.x, sz.y));
573             }
574         }
575 
576         TestLogging.recordMotionEvent(
577                 TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
578 
579         if (!mDeviceState.isUserUnlocked()) {
580             return;
581         }
582 
583         Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride(
584                 TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
585 
586         final int action = event.getAction();
587         if (action == ACTION_DOWN) {
588             mRotationTouchHelper.setOrientationTransformIfNeeded(event);
589 
590             if (!mDeviceState.isOneHandedModeActive()
591                     && mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
592                 // Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
593                 // onConsumerInactive and wipe the previous gesture state
594                 GestureState prevGestureState = new GestureState(mGestureState);
595                 GestureState newGestureState = createGestureState(mGestureState);
596                 newGestureState.setSwipeUpStartTimeMs(SystemClock.uptimeMillis());
597                 mConsumer.onConsumerAboutToBeSwitched();
598                 mGestureState = newGestureState;
599                 mConsumer = newConsumer(prevGestureState, mGestureState, event);
600 
601                 ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
602                 mUncheckedConsumer = mConsumer;
603             } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()) {
604                 mGestureState = createGestureState(mGestureState);
605                 ActivityManager.RunningTaskInfo runningTask = mGestureState.getRunningTask();
606                 if (mDeviceState.canTriggerAssistantAction(event, runningTask)) {
607                     // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
608                     // should not interrupt it. QuickSwitch assumes that interruption can only
609                     // happen if the next gesture is also quick switch.
610                     mUncheckedConsumer = new AssistantInputConsumer(
611                             this,
612                             mGestureState,
613                             InputConsumer.NO_OP, mInputMonitorCompat,
614                             mDeviceState,
615                             event);
616                 } else if (mDeviceState.canTriggerOneHandedAction(event)) {
617                     // Consume gesture event for triggering one handed feature.
618                     mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
619                         InputConsumer.NO_OP, mInputMonitorCompat);
620                 } else {
621                     mUncheckedConsumer = InputConsumer.NO_OP;
622                 }
623             } else if (mDeviceState.canTriggerOneHandedAction(event)) {
624                 // Consume gesture event for triggering one handed feature.
625                 mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
626                         InputConsumer.NO_OP, mInputMonitorCompat);
627             } else {
628                 mUncheckedConsumer = InputConsumer.NO_OP;
629             }
630         } else {
631             // Other events
632             if (mUncheckedConsumer != InputConsumer.NO_OP) {
633                 // Only transform the event if we are handling it in a proper consumer
634                 mRotationTouchHelper.setOrientationTransformIfNeeded(event);
635             }
636         }
637 
638         if (mUncheckedConsumer != InputConsumer.NO_OP) {
639             switch (event.getActionMasked()) {
640                 case ACTION_DOWN:
641                 case ACTION_UP:
642                     ActiveGestureLog.INSTANCE.addLog("onMotionEvent("
643                             + (int) event.getRawX() + ", " + (int) event.getRawY() + ")",
644                             event.getActionMasked());
645                     break;
646                 default:
647                     ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
648                     break;
649             }
650         }
651 
652         boolean cancelGesture = mGestureState.getActivityInterface() != null
653                 && mGestureState.getActivityInterface().shouldCancelCurrentGesture();
654         boolean cleanUpConsumer = (action == ACTION_UP || action == ACTION_CANCEL || cancelGesture)
655                 && mConsumer != null
656                 && !mConsumer.getActiveConsumerInHierarchy().isConsumerDetachedFromGesture();
657         if (cancelGesture) {
658             event.setAction(ACTION_CANCEL);
659         }
660         mUncheckedConsumer.onMotionEvent(event);
661 
662         if (cleanUpConsumer) {
663             reset();
664         }
665         TraceHelper.INSTANCE.endFlagsOverride(traceToken);
666         ProtoTracer.INSTANCE.get(this).scheduleFrameUpdate();
667     }
668 
createGestureState(GestureState previousGestureState)669     public GestureState createGestureState(GestureState previousGestureState) {
670         GestureState gestureState = new GestureState(mOverviewComponentObserver,
671                 ActiveGestureLog.INSTANCE.generateAndSetLogId());
672         if (mTaskAnimationManager.isRecentsAnimationRunning()) {
673             gestureState.updateRunningTask(previousGestureState.getRunningTask());
674             gestureState.updateLastStartedTaskId(previousGestureState.getLastStartedTaskId());
675             gestureState.updatePreviouslyAppearedTaskIds(
676                     previousGestureState.getPreviouslyAppearedTaskIds());
677         } else {
678             gestureState.updateRunningTasks(TraceHelper.allowIpcs("getRunningTask.0",
679                     () -> mAM.getRunningTasks(false /* filterOnlyVisibleRecents */)));
680         }
681         return gestureState;
682     }
683 
newConsumer(GestureState previousGestureState, GestureState newGestureState, MotionEvent event)684     private InputConsumer newConsumer(GestureState previousGestureState,
685             GestureState newGestureState, MotionEvent event) {
686         AnimatedFloat progressProxy = mSwipeUpProxyProvider.apply(mGestureState);
687         if (progressProxy != null) {
688             return new ProgressDelegateInputConsumer(this, mTaskAnimationManager,
689                     mGestureState, mInputMonitorCompat, progressProxy);
690         }
691 
692         boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
693 
694         if (!mDeviceState.isUserUnlocked()) {
695             if (canStartSystemGesture) {
696                 // This handles apps launched in direct boot mode (e.g. dialer) as well as apps
697                 // launched while device is locked even after exiting direct boot mode (e.g. camera).
698                 return createDeviceLockedInputConsumer(newGestureState);
699             } else {
700                 return getDefaultInputConsumer();
701             }
702         }
703 
704         // When there is an existing recents animation running, bypass systemState check as this is
705         // a followup gesture and the first gesture started in a valid system state.
706         InputConsumer base = canStartSystemGesture
707                 || previousGestureState.isRecentsAnimationRunning()
708                         ? newBaseConsumer(previousGestureState, newGestureState, event)
709                         : getDefaultInputConsumer();
710         if (mDeviceState.isGesturalNavMode()) {
711             handleOrientationSetup(base);
712         }
713         if (mDeviceState.isFullyGesturalNavMode()) {
714             if (mDeviceState.canTriggerAssistantAction(event, newGestureState.getRunningTask())) {
715                 base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat,
716                         mDeviceState, event);
717             }
718 
719             // If Taskbar is present, we listen for long press to unstash it.
720             BaseActivityInterface activityInterface = newGestureState.getActivityInterface();
721             StatefulActivity activity = activityInterface.getCreatedActivity();
722             if (activity != null && activity.getDeviceProfile().isTaskbarPresent) {
723                 base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat,
724                         mTaskbarManager.getCurrentActivityContext());
725             }
726 
727             // If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
728             // instead of going all the way home when a swipe up is detected.
729             if (mDeviceState.isBubblesExpanded() || mDeviceState.isGlobalActionsShowing()) {
730                 base = new SysUiOverlayInputConsumer(
731                         getBaseContext(), mDeviceState, mInputMonitorCompat);
732             }
733 
734             if (mDeviceState.isScreenPinningActive()) {
735                 // Note: we only allow accessibility to wrap this, and it replaces the previous
736                 // base input consumer (which should be NO_OP anyway since topTaskLocked == true).
737                 base = new ScreenPinnedInputConsumer(this, newGestureState);
738             }
739 
740             if (mDeviceState.canTriggerOneHandedAction(event)) {
741                 base = new OneHandedModeInputConsumer(this, mDeviceState, base,
742                         mInputMonitorCompat);
743             }
744 
745             if (mDeviceState.isAccessibilityMenuAvailable()) {
746                 base = new AccessibilityInputConsumer(this, mDeviceState, base,
747                         mInputMonitorCompat);
748             }
749         } else {
750             if (mDeviceState.isScreenPinningActive()) {
751                 base = getDefaultInputConsumer();
752             }
753 
754             if (mDeviceState.canTriggerOneHandedAction(event)) {
755                 base = new OneHandedModeInputConsumer(this, mDeviceState, base,
756                         mInputMonitorCompat);
757             }
758         }
759         return base;
760     }
761 
handleOrientationSetup(InputConsumer baseInputConsumer)762     private void handleOrientationSetup(InputConsumer baseInputConsumer) {
763         baseInputConsumer.notifyOrientationSetup();
764     }
765 
newBaseConsumer(GestureState previousGestureState, GestureState gestureState, MotionEvent event)766     private InputConsumer newBaseConsumer(GestureState previousGestureState,
767             GestureState gestureState, MotionEvent event) {
768         if (mDeviceState.isKeyguardShowingOccluded()) {
769             // This handles apps showing over the lockscreen (e.g. camera)
770             return createDeviceLockedInputConsumer(gestureState);
771         }
772 
773         // Use overview input consumer for sharesheets on top of home.
774         boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
775                 && gestureState.getRunningTask() != null
776                 && ACTION_CHOOSER.equals(gestureState.getRunningTask().baseIntent.getAction());
777         if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
778             // In the case where we are in the excluded assistant state, ignore it and treat the
779             // running activity as the task behind the assistant
780             gestureState.updateRunningTask(TraceHelper.allowIpcs("getRunningTask.assistant",
781                     () -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
782             ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
783             ComponentName runningComponent =
784                     gestureState.getRunningTask().baseIntent.getComponent();
785             forceOverviewInputConsumer =
786                     runningComponent != null && runningComponent.equals(homeComponent);
787         }
788 
789         if (ENABLE_QUICKSTEP_LIVE_TILE.get()
790                 && gestureState.getActivityInterface().isInLiveTileMode()) {
791             return createOverviewInputConsumer(
792                     previousGestureState, gestureState, event, forceOverviewInputConsumer);
793         } else if (gestureState.getRunningTask() == null) {
794             return getDefaultInputConsumer();
795         } else if (previousGestureState.isRunningAnimationToLauncher()
796                 || gestureState.getActivityInterface().isResumed()
797                 || forceOverviewInputConsumer) {
798             return createOverviewInputConsumer(
799                     previousGestureState, gestureState, event, forceOverviewInputConsumer);
800         } else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
801             return getDefaultInputConsumer();
802         } else {
803             return createOtherActivityInputConsumer(gestureState, event);
804         }
805     }
806 
getSwipeUpHandlerFactory()807     public AbsSwipeUpHandler.Factory getSwipeUpHandlerFactory() {
808         return !mOverviewComponentObserver.isHomeAndOverviewSame()
809                 ? mFallbackSwipeHandlerFactory : mLauncherSwipeHandlerFactory;
810     }
811 
createOtherActivityInputConsumer(GestureState gestureState, MotionEvent event)812     private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
813             MotionEvent event) {
814 
815         final AbsSwipeUpHandler.Factory factory = getSwipeUpHandlerFactory();
816         final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame()
817                 || gestureState.getActivityInterface().deferStartingActivity(mDeviceState, event);
818         final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
819         return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
820                 gestureState, shouldDefer, this::onConsumerInactive,
821                 mInputMonitorCompat, mInputEventReceiver, disableHorizontalSwipe, factory);
822     }
823 
createDeviceLockedInputConsumer(GestureState gestureState)824     private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState) {
825         if (mDeviceState.isFullyGesturalNavMode() && gestureState.getRunningTask() != null) {
826             return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
827                     gestureState, mInputMonitorCompat);
828         } else {
829             return getDefaultInputConsumer();
830         }
831     }
832 
createOverviewInputConsumer(GestureState previousGestureState, GestureState gestureState, MotionEvent event, boolean forceOverviewInputConsumer)833     public InputConsumer createOverviewInputConsumer(GestureState previousGestureState,
834             GestureState gestureState, MotionEvent event,
835             boolean forceOverviewInputConsumer) {
836         StatefulActivity activity = gestureState.getActivityInterface().getCreatedActivity();
837         if (activity == null) {
838             return getDefaultInputConsumer();
839         }
840 
841         if (activity.getRootView().hasWindowFocus()
842                 || previousGestureState.isRunningAnimationToLauncher()
843                 || (ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
844                     && forceOverviewInputConsumer)
845                 || (ENABLE_QUICKSTEP_LIVE_TILE.get()
846                 && gestureState.getActivityInterface().isInLiveTileMode())) {
847             return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
848                     false /* startingInActivityBounds */);
849         } else {
850             final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
851             return new OverviewWithoutFocusInputConsumer(activity, mDeviceState, gestureState,
852                     mInputMonitorCompat, disableHorizontalSwipe);
853         }
854     }
855 
856     /**
857      * To be called by the consumer when it's no longer active. This can be called by any consumer
858      * in the hierarchy at any point during the gesture (ie. if a delegate consumer starts
859      * intercepting touches, the base consumer can try to call this).
860      */
onConsumerInactive(InputConsumer caller)861     private void onConsumerInactive(InputConsumer caller) {
862         if (mConsumer != null && mConsumer.getActiveConsumerInHierarchy() == caller) {
863             reset();
864         }
865     }
866 
reset()867     private void reset() {
868         mConsumer = mUncheckedConsumer = getDefaultInputConsumer();
869         mGestureState = DEFAULT_STATE;
870         // By default, use batching of the input events, but check receiver before using in the rare
871         // case that the monitor was disposed before the swipe settled
872         if (mInputEventReceiver != null) {
873             mInputEventReceiver.setBatchingEnabled(true);
874         }
875     }
876 
877     /**
878      * Returns the {@link ResetGestureInputConsumer} if user is unlocked, else NO_OP.
879      */
getDefaultInputConsumer()880     private @NonNull InputConsumer getDefaultInputConsumer() {
881         if (mResetGestureInputConsumer != null) {
882             return mResetGestureInputConsumer;
883         } else {
884             // mResetGestureInputConsumer isn't initialized until onUserUnlocked(), so reset to
885             // NO_OP until then (we never want these to be null).
886             return InputConsumer.NO_OP;
887         }
888     }
889 
preloadOverview(boolean fromInit)890     private void preloadOverview(boolean fromInit) {
891         if (!mDeviceState.isUserUnlocked()) {
892             return;
893         }
894 
895         if (mDeviceState.isButtonNavMode() && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
896             // Prevent the overview from being started before the real home on first boot.
897             return;
898         }
899 
900         if (RestoreDbTask.isPending(this) || !mDeviceState.isUserSetupComplete()) {
901             // Preloading while a restore is pending may cause launcher to start the restore
902             // too early.
903             return;
904         }
905 
906         final BaseActivityInterface activityInterface =
907                 mOverviewComponentObserver.getActivityInterface();
908         final Intent overviewIntent = new Intent(
909                 mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
910         if (activityInterface.getCreatedActivity() != null && fromInit) {
911             // The activity has been created before the initialization of overview service. It is
912             // usually happens when booting or launcher is the top activity, so we should already
913             // have the latest state.
914             return;
915         }
916 
917         mTaskAnimationManager.preloadRecentsAnimation(overviewIntent);
918     }
919 
920     @Override
onConfigurationChanged(Configuration newConfig)921     public void onConfigurationChanged(Configuration newConfig) {
922         if (!mDeviceState.isUserUnlocked()) {
923             return;
924         }
925         final BaseActivityInterface activityInterface =
926                 mOverviewComponentObserver.getActivityInterface();
927         final BaseDraggingActivity activity = activityInterface.getCreatedActivity();
928         if (activity == null || activity.isStarted()) {
929             // We only care about the existing background activity.
930             return;
931         }
932         if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
933                 activity.getResources().getConfiguration().diff(newConfig))) {
934             // Since navBar gestural height are different between portrait and landscape,
935             // can handle orientation changes and refresh navigation gestural region through
936             // onOneHandedModeChanged()
937             int newGesturalHeight = ResourceUtils.getNavbarSize(
938                     ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
939                     getApplicationContext().getResources());
940             mDeviceState.onOneHandedModeChanged(newGesturalHeight);
941             return;
942         }
943 
944         preloadOverview(false /* fromInit */);
945     }
946 
947     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs)948     protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
949         if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
950             LinkedList<String> args = new LinkedList(Arrays.asList(rawArgs));
951             switch (args.pollFirst()) {
952                 case "cmd":
953                     if (args.peekFirst() == null) {
954                         printAvailableCommands(pw);
955                     } else {
956                         onCommand(pw, args);
957                     }
958                     break;
959             }
960         } else {
961             // Dump everything
962             FeatureFlags.dump(pw);
963             if (mDeviceState.isUserUnlocked()) {
964                 PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
965             }
966             mDeviceState.dump(pw);
967             if (mOverviewComponentObserver != null) {
968                 mOverviewComponentObserver.dump(pw);
969             }
970             if (mOverviewCommandHelper != null) {
971                 mOverviewCommandHelper.dump(pw);
972             }
973             if (mGestureState != null) {
974                 mGestureState.dump(pw);
975             }
976             pw.println("Input state:");
977             pw.println("  mInputMonitorCompat=" + mInputMonitorCompat);
978             pw.println("  mInputEventReceiver=" + mInputEventReceiver);
979             SysUINavigationMode.INSTANCE.get(this).dump(pw);
980             pw.println("TouchState:");
981             BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
982                     : mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
983             boolean resumed = mOverviewComponentObserver != null
984                     && mOverviewComponentObserver.getActivityInterface().isResumed();
985             pw.println("  createdOverviewActivity=" + createdOverviewActivity);
986             pw.println("  resumed=" + resumed);
987             pw.println("  mConsumer=" + mConsumer.getName());
988             ActiveGestureLog.INSTANCE.dump("", pw);
989             RecentsModel.INSTANCE.get(this).dump("", pw);
990             pw.println("ProtoTrace:");
991             pw.println("  file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
992         }
993     }
994 
printAvailableCommands(PrintWriter pw)995     private void printAvailableCommands(PrintWriter pw) {
996         pw.println("Available commands:");
997         pw.println("  clear-touch-log: Clears the touch interaction log");
998     }
999 
onCommand(PrintWriter pw, LinkedList<String> args)1000     private void onCommand(PrintWriter pw, LinkedList<String> args) {
1001         switch (args.pollFirst()) {
1002             case "clear-touch-log":
1003                 ActiveGestureLog.INSTANCE.clear();
1004                 break;
1005         }
1006     }
1007 
createLauncherSwipeHandler( GestureState gestureState, long touchTimeMs)1008     private AbsSwipeUpHandler createLauncherSwipeHandler(
1009             GestureState gestureState, long touchTimeMs) {
1010         return new LauncherSwipeHandlerV2(this, mDeviceState, mTaskAnimationManager,
1011                 gestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning(),
1012                 mInputConsumer);
1013     }
1014 
createFallbackSwipeHandler( GestureState gestureState, long touchTimeMs)1015     private AbsSwipeUpHandler createFallbackSwipeHandler(
1016             GestureState gestureState, long touchTimeMs) {
1017         return new FallbackSwipeHandler(this, mDeviceState, mTaskAnimationManager,
1018                 gestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning(),
1019                 mInputConsumer);
1020     }
1021 
1022     @Override
writeToProto(LauncherTraceProto.Builder proto)1023     public void writeToProto(LauncherTraceProto.Builder proto) {
1024         TouchInteractionServiceProto.Builder serviceProto =
1025             TouchInteractionServiceProto.newBuilder();
1026         serviceProto.setServiceConnected(true);
1027 
1028         if (mOverviewComponentObserver != null) {
1029             mOverviewComponentObserver.writeToProto(serviceProto);
1030         }
1031         mConsumer.writeToProto(serviceProto);
1032 
1033         proto.setTouchInteractionService(serviceProto);
1034     }
1035 }
1036