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