1 /* 2 * Copyright (C) 2019 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.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 19 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 20 import static android.view.Display.DEFAULT_DISPLAY; 21 22 import static com.android.launcher3.util.DisplayController.CHANGE_ALL; 23 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE; 24 import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION; 25 import static com.android.launcher3.util.NavigationMode.NO_BUTTON; 26 import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS; 27 import static com.android.launcher3.util.NavigationMode.TWO_BUTTONS; 28 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED; 29 import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED; 30 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; 31 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; 32 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY; 33 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED; 34 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED; 35 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING; 36 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING; 37 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED; 38 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; 39 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; 40 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN; 41 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; 42 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE; 43 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; 44 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; 45 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; 46 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; 47 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; 48 49 import android.app.ActivityTaskManager; 50 import android.content.Context; 51 import android.graphics.Region; 52 import android.inputmethodservice.InputMethodService; 53 import android.net.Uri; 54 import android.os.RemoteException; 55 import android.os.SystemProperties; 56 import android.provider.Settings; 57 import android.view.MotionEvent; 58 import android.view.ViewConfiguration; 59 60 import androidx.annotation.BinderThread; 61 import androidx.annotation.NonNull; 62 63 import com.android.launcher3.util.DisplayController; 64 import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener; 65 import com.android.launcher3.util.DisplayController.Info; 66 import com.android.launcher3.util.NavigationMode; 67 import com.android.launcher3.util.SettingsCache; 68 import com.android.quickstep.TopTaskTracker.CachedTaskInfo; 69 import com.android.quickstep.util.NavBarPosition; 70 import com.android.systemui.shared.system.ActivityManagerWrapper; 71 import com.android.systemui.shared.system.QuickStepContract; 72 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; 73 import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat; 74 import com.android.systemui.shared.system.TaskStackChangeListener; 75 import com.android.systemui.shared.system.TaskStackChangeListeners; 76 77 import java.io.PrintWriter; 78 import java.util.ArrayList; 79 80 /** 81 * Manages the state of the system during a swipe up gesture. 82 */ 83 public class RecentsAnimationDeviceState implements DisplayInfoChangeListener { 84 85 static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; 86 87 // TODO: Move to quickstep contract 88 private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 9; 89 private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 2; 90 91 private final Context mContext; 92 private final DisplayController mDisplayController; 93 private final int mDisplayId; 94 private final RotationTouchHelper mRotationTouchHelper; 95 private final TaskStackChangeListener mPipListener; 96 // Cache for better performance since it doesn't change at runtime. 97 private final boolean mCanImeRenderGesturalNavButtons = 98 InputMethodService.canImeRenderGesturalNavButtons(); 99 100 private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>(); 101 102 private @SystemUiStateFlags int mSystemUiStateFlags = QuickStepContract.SYSUI_STATE_AWAKE; 103 private NavigationMode mMode = THREE_BUTTONS; 104 private NavBarPosition mNavBarPosition; 105 106 private final Region mDeferredGestureRegion = new Region(); 107 private boolean mAssistantAvailable; 108 private float mAssistantVisibility; 109 private boolean mIsUserSetupComplete; 110 private boolean mIsOneHandedModeEnabled; 111 private boolean mIsSwipeToNotificationEnabled; 112 private final boolean mIsOneHandedModeSupported; 113 private boolean mPipIsActive; 114 115 private int mGestureBlockingTaskId = -1; 116 private @NonNull Region mExclusionRegion = new Region(); 117 private SystemGestureExclusionListenerCompat mExclusionListener; 118 RecentsAnimationDeviceState(Context context)119 public RecentsAnimationDeviceState(Context context) { 120 this(context, false); 121 } 122 123 /** 124 * @param isInstanceForTouches {@code true} if this is the persistent instance being used for 125 * gesture touch handling 126 */ RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches)127 public RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches) { 128 mContext = context; 129 mDisplayController = DisplayController.INSTANCE.get(context); 130 mDisplayId = DEFAULT_DISPLAY; 131 mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false); 132 mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context); 133 if (isInstanceForTouches) { 134 // rotationTouchHelper doesn't get initialized after being destroyed, so only destroy 135 // if primary TouchInteractionService instance needs to be destroyed. 136 mRotationTouchHelper.init(); 137 runOnDestroy(mRotationTouchHelper::destroy); 138 } 139 140 // Register for exclusion updates 141 mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) { 142 @Override 143 @BinderThread 144 public void onExclusionChanged(Region region) { 145 if (region == null) { 146 // Don't think this is possible but just in case, don't let it be null. 147 region = new Region(); 148 } 149 // Assignments are atomic, it should be safe on binder thread 150 mExclusionRegion = region; 151 } 152 }; 153 runOnDestroy(mExclusionListener::unregister); 154 155 // Register for display changes changes 156 mDisplayController.addChangeListener(this); 157 onDisplayInfoChanged(context, mDisplayController.getInfo(), CHANGE_ALL); 158 runOnDestroy(() -> mDisplayController.removeChangeListener(this)); 159 160 SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext); 161 if (mIsOneHandedModeSupported) { 162 Uri oneHandedUri = Settings.Secure.getUriFor(ONE_HANDED_ENABLED); 163 SettingsCache.OnChangeListener onChangeListener = 164 enabled -> mIsOneHandedModeEnabled = enabled; 165 settingsCache.register(oneHandedUri, onChangeListener); 166 mIsOneHandedModeEnabled = settingsCache.getValue(oneHandedUri); 167 runOnDestroy(() -> settingsCache.unregister(oneHandedUri, onChangeListener)); 168 } else { 169 mIsOneHandedModeEnabled = false; 170 } 171 172 Uri swipeBottomNotificationUri = 173 Settings.Secure.getUriFor(ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED); 174 SettingsCache.OnChangeListener onChangeListener = 175 enabled -> mIsSwipeToNotificationEnabled = enabled; 176 settingsCache.register(swipeBottomNotificationUri, onChangeListener); 177 mIsSwipeToNotificationEnabled = settingsCache.getValue(swipeBottomNotificationUri); 178 runOnDestroy(() -> settingsCache.unregister(swipeBottomNotificationUri, onChangeListener)); 179 180 Uri setupCompleteUri = Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE); 181 mIsUserSetupComplete = settingsCache.getValue(setupCompleteUri, 0); 182 if (!mIsUserSetupComplete) { 183 SettingsCache.OnChangeListener userSetupChangeListener = e -> mIsUserSetupComplete = e; 184 settingsCache.register(setupCompleteUri, userSetupChangeListener); 185 runOnDestroy(() -> settingsCache.unregister(setupCompleteUri, userSetupChangeListener)); 186 } 187 188 try { 189 mPipIsActive = ActivityTaskManager.getService().getRootTaskInfo( 190 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED) != null; 191 } catch (RemoteException e) { 192 // Do nothing 193 } 194 mPipListener = new TaskStackChangeListener() { 195 @Override 196 public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { 197 mPipIsActive = true; 198 } 199 200 @Override 201 public void onActivityUnpinned() { 202 mPipIsActive = false; 203 } 204 }; 205 TaskStackChangeListeners.getInstance().registerTaskStackListener(mPipListener); 206 runOnDestroy(() -> 207 TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mPipListener)); 208 } 209 runOnDestroy(Runnable action)210 private void runOnDestroy(Runnable action) { 211 mOnDestroyActions.add(action); 212 } 213 214 /** 215 * Cleans up all the registered listeners and receivers. 216 */ destroy()217 public void destroy() { 218 for (Runnable r : mOnDestroyActions) { 219 r.run(); 220 } 221 } 222 223 /** 224 * Adds a listener for the nav mode change, guaranteed to be called after the device state's 225 * mode has changed. 226 */ addNavigationModeChangedCallback(Runnable callback)227 public void addNavigationModeChangedCallback(Runnable callback) { 228 DisplayController.DisplayInfoChangeListener listener = (context, info, flags) -> { 229 if ((flags & CHANGE_NAVIGATION_MODE) != 0) { 230 callback.run(); 231 } 232 }; 233 mDisplayController.addChangeListener(listener); 234 callback.run(); 235 runOnDestroy(() -> mDisplayController.removeChangeListener(listener)); 236 } 237 238 @Override onDisplayInfoChanged(Context context, Info info, int flags)239 public void onDisplayInfoChanged(Context context, Info info, int flags) { 240 if ((flags & (CHANGE_ROTATION | CHANGE_NAVIGATION_MODE)) != 0) { 241 mMode = info.navigationMode; 242 mNavBarPosition = new NavBarPosition(mMode, info); 243 244 if (mMode == NO_BUTTON) { 245 mExclusionListener.register(); 246 } else { 247 mExclusionListener.unregister(); 248 } 249 } 250 } 251 onOneHandedModeChanged(int newGesturalHeight)252 public void onOneHandedModeChanged(int newGesturalHeight) { 253 mRotationTouchHelper.setGesturalHeight(newGesturalHeight); 254 } 255 256 /** 257 * @return the nav bar position for the current nav bar mode and display rotation. 258 */ getNavBarPosition()259 public NavBarPosition getNavBarPosition() { 260 return mNavBarPosition; 261 } 262 263 /** 264 * @return whether the current nav mode is fully gestural. 265 */ isFullyGesturalNavMode()266 public boolean isFullyGesturalNavMode() { 267 return mMode == NO_BUTTON; 268 } 269 270 /** 271 * @return whether the current nav mode has some gestures (either 2 or 0 button mode). 272 */ isGesturalNavMode()273 public boolean isGesturalNavMode() { 274 return mMode.hasGestures; 275 } 276 277 /** 278 * @return whether the current nav mode is 2-button-based. 279 */ isTwoButtonNavMode()280 public boolean isTwoButtonNavMode() { 281 return mMode == TWO_BUTTONS; 282 } 283 284 /** 285 * @return whether the current nav mode is button-based. 286 */ isButtonNavMode()287 public boolean isButtonNavMode() { 288 return mMode == THREE_BUTTONS; 289 } 290 291 /** 292 * @return the display id for the display that Launcher is running on. 293 */ getDisplayId()294 public int getDisplayId() { 295 return mDisplayId; 296 } 297 298 /** 299 * @return whether the user has completed setup wizard 300 */ isUserSetupComplete()301 public boolean isUserSetupComplete() { 302 return mIsUserSetupComplete; 303 } 304 305 /** 306 * Sets the task id where gestures should be blocked 307 */ setGestureBlockingTaskId(int taskId)308 public void setGestureBlockingTaskId(int taskId) { 309 mGestureBlockingTaskId = taskId; 310 } 311 312 /** 313 * @return whether the given running task info matches the gesture-blocked task. 314 */ isGestureBlockedTask(CachedTaskInfo taskInfo)315 public boolean isGestureBlockedTask(CachedTaskInfo taskInfo) { 316 return taskInfo != null && taskInfo.getTaskId() == mGestureBlockingTaskId; 317 } 318 319 /** 320 * Updates the system ui state flags from SystemUI. 321 */ setSystemUiFlags(int stateFlags)322 public void setSystemUiFlags(int stateFlags) { 323 mSystemUiStateFlags = stateFlags; 324 } 325 326 /** 327 * @return the system ui state flags. 328 */ 329 // TODO(141886704): See if we can remove this getSystemUiStateFlags()330 public int getSystemUiStateFlags() { 331 return mSystemUiStateFlags; 332 } 333 334 /** 335 * @return whether SystemUI is in a state where we can start a system gesture. 336 */ canStartSystemGesture()337 public boolean canStartSystemGesture() { 338 boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0 339 || (mSystemUiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0 340 || mRotationTouchHelper.isTaskListFrozen(); 341 return canStartWithNavHidden && canStartTrackpadGesture(); 342 } 343 344 /** 345 * @return whether SystemUI is in a state where we can start a system gesture from the trackpad. 346 * Trackpad gestures can start even when the nav bar / task bar is hidden in sticky immersive 347 * mode. 348 */ canStartTrackpadGesture()349 public boolean canStartTrackpadGesture() { 350 return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0 351 && (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0 352 && (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0 353 && (mSystemUiStateFlags & SYSUI_STATE_MAGNIFICATION_OVERLAP) == 0 354 && ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 355 || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0) 356 && (mSystemUiStateFlags & SYSUI_STATE_DEVICE_DREAMING) == 0; 357 } 358 359 /** 360 * @return whether the keyguard is showing and is occluded by an app showing above the keyguard 361 * (like camera or maps) 362 */ isKeyguardShowingOccluded()363 public boolean isKeyguardShowingOccluded() { 364 return (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0; 365 } 366 367 /** 368 * @return whether screen pinning is enabled and active 369 */ isScreenPinningActive()370 public boolean isScreenPinningActive() { 371 return (mSystemUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0; 372 } 373 374 /** 375 * @return whether assistant gesture is constraint 376 */ isAssistantGestureIsConstrained()377 public boolean isAssistantGestureIsConstrained() { 378 return (mSystemUiStateFlags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0; 379 } 380 381 /** 382 * @return whether the bubble stack is expanded 383 */ isBubblesExpanded()384 public boolean isBubblesExpanded() { 385 return (mSystemUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0; 386 } 387 388 /** 389 * @return whether notification panel is expanded 390 */ isNotificationPanelExpanded()391 public boolean isNotificationPanelExpanded() { 392 return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0; 393 } 394 395 /** 396 * @return whether the global actions dialog is showing 397 */ isSystemUiDialogShowing()398 public boolean isSystemUiDialogShowing() { 399 return (mSystemUiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0; 400 } 401 402 /** 403 * @return whether lock-task mode is active 404 */ isLockToAppActive()405 public boolean isLockToAppActive() { 406 return ActivityManagerWrapper.getInstance().isLockToAppActive(); 407 } 408 409 /** 410 * @return whether the accessibility menu is available. 411 */ isAccessibilityMenuAvailable()412 public boolean isAccessibilityMenuAvailable() { 413 return (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; 414 } 415 416 /** 417 * @return whether the accessibility menu shortcut is available. 418 */ isAccessibilityMenuShortcutAvailable()419 public boolean isAccessibilityMenuShortcutAvailable() { 420 return (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; 421 } 422 423 /** 424 * @return whether home is disabled (either by SUW/SysUI/device policy) 425 */ isHomeDisabled()426 public boolean isHomeDisabled() { 427 return (mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0; 428 } 429 430 /** 431 * @return whether overview is disabled (either by SUW/SysUI/device policy) 432 */ isOverviewDisabled()433 public boolean isOverviewDisabled() { 434 return (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0; 435 } 436 437 /** 438 * @return whether one-handed mode is enabled and active 439 */ isOneHandedModeActive()440 public boolean isOneHandedModeActive() { 441 return (mSystemUiStateFlags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0; 442 } 443 444 /** 445 * Sets the region in screen space where the gestures should be deferred (ie. due to specific 446 * nav bar ui). 447 */ setDeferredGestureRegion(Region deferredGestureRegion)448 public void setDeferredGestureRegion(Region deferredGestureRegion) { 449 mDeferredGestureRegion.set(deferredGestureRegion); 450 } 451 452 /** 453 * @return whether the given {@param event} is in the deferred gesture region indicating that 454 * the Launcher should not immediately start the recents animation until the gesture 455 * passes a certain threshold. 456 */ isInDeferredGestureRegion(MotionEvent event)457 public boolean isInDeferredGestureRegion(MotionEvent event) { 458 return mDeferredGestureRegion.contains((int) event.getX(), (int) event.getY()); 459 } 460 461 /** 462 * @return whether the given {@param event} is in the app-requested gesture-exclusion region. 463 * This is only used for quickswitch, and not swipe up. 464 */ isInExclusionRegion(MotionEvent event)465 public boolean isInExclusionRegion(MotionEvent event) { 466 // mExclusionRegion can change on binder thread, use a local instance here. 467 Region exclusionRegion = mExclusionRegion; 468 return mMode == NO_BUTTON 469 && exclusionRegion.contains((int) event.getX(), (int) event.getY()); 470 } 471 472 /** 473 * Sets whether the assistant is available. 474 */ setAssistantAvailable(boolean assistantAvailable)475 public void setAssistantAvailable(boolean assistantAvailable) { 476 mAssistantAvailable = assistantAvailable; 477 } 478 479 /** 480 * Sets the visibility fraction of the assistant. 481 */ setAssistantVisibility(float visibility)482 public void setAssistantVisibility(float visibility) { 483 mAssistantVisibility = visibility; 484 } 485 486 /** 487 * @return the visibility fraction of the assistant. 488 */ getAssistantVisibility()489 public float getAssistantVisibility() { 490 return mAssistantVisibility; 491 } 492 493 /** 494 * @param ev An ACTION_DOWN motion event 495 * @return whether the given motion event can trigger the assistant over the current task. 496 */ canTriggerAssistantAction(MotionEvent ev)497 public boolean canTriggerAssistantAction(MotionEvent ev) { 498 return mAssistantAvailable 499 && !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags) 500 && mRotationTouchHelper.touchInAssistantRegion(ev) 501 && !isLockToAppActive(); 502 } 503 504 /** 505 * One handed gestural in quickstep only active on NO_BUTTON, TWO_BUTTONS, and portrait mode 506 * 507 * @param ev The touch screen motion event. 508 * @return whether the given motion event can trigger the one handed mode. 509 */ canTriggerOneHandedAction(MotionEvent ev)510 public boolean canTriggerOneHandedAction(MotionEvent ev) { 511 if (!mIsOneHandedModeSupported) { 512 return false; 513 } 514 515 if (mIsOneHandedModeEnabled) { 516 final Info displayInfo = mDisplayController.getInfo(); 517 return (mRotationTouchHelper.touchInOneHandedModeRegion(ev) 518 && (displayInfo.currentSize.x < displayInfo.currentSize.y)); 519 } 520 return false; 521 } 522 isOneHandedModeEnabled()523 public boolean isOneHandedModeEnabled() { 524 return mIsOneHandedModeEnabled; 525 } 526 isSwipeToNotificationEnabled()527 public boolean isSwipeToNotificationEnabled() { 528 return mIsSwipeToNotificationEnabled; 529 } 530 isPipActive()531 public boolean isPipActive() { 532 return mPipIsActive; 533 } 534 getRotationTouchHelper()535 public RotationTouchHelper getRotationTouchHelper() { 536 return mRotationTouchHelper; 537 } 538 539 /** Returns whether IME is rendering nav buttons, and IME is currently showing. */ isImeRenderingNavButtons()540 public boolean isImeRenderingNavButtons() { 541 return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON 542 && ((mSystemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0); 543 } 544 545 /** 546 * Returns the touch slop for {@link InputConsumer}s to compare against before pilfering 547 * pointers. Note that this is squared because it expects to be compared against 548 * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event). 549 */ getSquaredTouchSlop()550 public float getSquaredTouchSlop() { 551 float slopMultiplier = isFullyGesturalNavMode() 552 ? QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL 553 : QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON; 554 float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); 555 return slopMultiplier * touchSlop * touchSlop; 556 } 557 getSystemUiStateString()558 public String getSystemUiStateString() { 559 return QuickStepContract.getSystemUiStateString(mSystemUiStateFlags); 560 } 561 dump(PrintWriter pw)562 public void dump(PrintWriter pw) { 563 pw.println("DeviceState:"); 564 pw.println(" canStartSystemGesture=" + canStartSystemGesture()); 565 pw.println(" systemUiFlags=" + mSystemUiStateFlags); 566 pw.println(" systemUiFlagsDesc=" + getSystemUiStateString()); 567 pw.println(" assistantAvailable=" + mAssistantAvailable); 568 pw.println(" assistantDisabled=" 569 + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags)); 570 pw.println(" isOneHandedModeEnabled=" + mIsOneHandedModeEnabled); 571 pw.println(" isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled); 572 pw.println(" deferredGestureRegion=" + mDeferredGestureRegion.getBounds()); 573 pw.println(" exclusionRegion=" + mExclusionRegion.getBounds()); 574 pw.println(" pipIsActive=" + mPipIsActive); 575 mRotationTouchHelper.dump(pw); 576 } 577 } 578