summaryrefslogtreecommitdiff
path: root/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
diff options
context:
space:
mode:
Diffstat (limited to 'quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java')
-rw-r--r--quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java158
1 files changed, 114 insertions, 44 deletions
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 1448a523b0..179612b77b 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -19,12 +19,13 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
-import static com.android.launcher3.util.NavigationMode.TWO_BUTTONS;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -54,23 +55,30 @@ import android.net.Uri;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.util.Log;
+import android.view.ISystemGestureExclusionListener;
+import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import android.view.WindowManagerGlobal;
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
+import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
-import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -82,15 +90,36 @@ import java.util.ArrayList;
*/
public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
+ private static final String TAG = "RecentsAnimationDeviceState";
+
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
// TODO: Move to quickstep contract
- private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 9;
- private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 2;
+ private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 3f;
+ private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 1.414f;
private final Context mContext;
private final DisplayController mDisplayController;
- private final int mDisplayId;
+
+ private final IWindowManager mIWindowManager;
+
+ @VisibleForTesting
+ final ISystemGestureExclusionListener mGestureExclusionListener =
+ new ISystemGestureExclusionListener.Stub() {
+ @BinderThread
+ @Override
+ public void onSystemGestureExclusionChanged(int displayId,
+ Region systemGestureExclusionRegion, Region unrestrictedOrNull) {
+ if (displayId != DEFAULT_DISPLAY) {
+ return;
+ }
+ // Assignments are atomic, it should be safe on binder thread. Also we don't
+ // think systemGestureExclusionRegion can be null but just in case, don't
+ // let mExclusionRegion be null.
+ mExclusionRegion = systemGestureExclusionRegion != null
+ ? systemGestureExclusionRegion : new Region();
+ }
+ };
private final RotationTouchHelper mRotationTouchHelper;
private final TaskStackChangeListener mPipListener;
// Cache for better performance since it doesn't change at runtime.
@@ -114,20 +143,31 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
private int mGestureBlockingTaskId = -1;
private @NonNull Region mExclusionRegion = new Region();
- private SystemGestureExclusionListenerCompat mExclusionListener;
+ private boolean mExclusionListenerRegistered;
public RecentsAnimationDeviceState(Context context) {
- this(context, false);
+ this(context, false, WindowManagerGlobal.getWindowManagerService());
+ }
+
+ public RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches) {
+ this(context, isInstanceForTouches, WindowManagerGlobal.getWindowManagerService());
+ }
+
+ @VisibleForTesting
+ RecentsAnimationDeviceState(Context context, IWindowManager windowManager) {
+ this(context, false, windowManager);
}
/**
* @param isInstanceForTouches {@code true} if this is the persistent instance being used for
* gesture touch handling
*/
- public RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches) {
+ RecentsAnimationDeviceState(
+ Context context, boolean isInstanceForTouches,
+ IWindowManager windowManager) {
mContext = context;
mDisplayController = DisplayController.INSTANCE.get(context);
- mDisplayId = DEFAULT_DISPLAY;
+ mIWindowManager = windowManager;
mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context);
if (isInstanceForTouches) {
@@ -138,19 +178,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
}
// Register for exclusion updates
- mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
- @Override
- @BinderThread
- public void onExclusionChanged(Region region) {
- if (region == null) {
- // Don't think this is possible but just in case, don't let it be null.
- region = new Region();
- }
- // Assignments are atomic, it should be safe on binder thread
- mExclusionRegion = region;
- }
- };
- runOnDestroy(mExclusionListener::unregister);
+ runOnDestroy(() -> unregisterExclusionListener());
// Register for display changes changes
mDisplayController.addChangeListener(this);
@@ -238,17 +266,57 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
@Override
public void onDisplayInfoChanged(Context context, Info info, int flags) {
if ((flags & (CHANGE_ROTATION | CHANGE_NAVIGATION_MODE)) != 0) {
- mMode = info.navigationMode;
+ mMode = info.getNavigationMode();
+ ActiveGestureLog.INSTANCE.setIsFullyGesturalNavMode(isFullyGesturalNavMode());
mNavBarPosition = new NavBarPosition(mMode, info);
if (mMode == NO_BUTTON) {
- mExclusionListener.register();
+ registerExclusionListener();
} else {
- mExclusionListener.unregister();
+ unregisterExclusionListener();
}
}
}
+ /**
+ * Registers {@link mGestureExclusionListener} for getting exclusion rect changes. Note that we
+ * make binder call on {@link UI_HELPER_EXECUTOR} to avoid jank.
+ */
+ public void registerExclusionListener() {
+ UI_HELPER_EXECUTOR.execute(() -> {
+ if (mExclusionListenerRegistered) {
+ return;
+ }
+ try {
+ mIWindowManager.registerSystemGestureExclusionListener(
+ mGestureExclusionListener, DEFAULT_DISPLAY);
+ mExclusionListenerRegistered = true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register window manager callbacks", e);
+ }
+ });
+ }
+
+ /**
+ * Unregisters {@link mGestureExclusionListener} if previously registered. We make binder call
+ * on same {@link UI_HELPER_EXECUTOR} as in {@link #registerExclusionListener()} so that
+ * read/write {@link mExclusionListenerRegistered} field is thread safe.
+ */
+ public void unregisterExclusionListener() {
+ UI_HELPER_EXECUTOR.execute(() -> {
+ if (!mExclusionListenerRegistered) {
+ return;
+ }
+ try {
+ mIWindowManager.unregisterSystemGestureExclusionListener(
+ mGestureExclusionListener, DEFAULT_DISPLAY);
+ mExclusionListenerRegistered = false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister window manager callbacks", e);
+ }
+ });
+ }
+
public void onOneHandedModeChanged(int newGesturalHeight) {
mRotationTouchHelper.setGesturalHeight(newGesturalHeight);
}
@@ -275,13 +343,6 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
}
/**
- * @return whether the current nav mode is 2-button-based.
- */
- public boolean isTwoButtonNavMode() {
- return mMode == TWO_BUTTONS;
- }
-
- /**
* @return whether the current nav mode is button-based.
*/
public boolean isButtonNavMode() {
@@ -292,7 +353,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
* @return the display id for the display that Launcher is running on.
*/
public int getDisplayId() {
- return mDisplayId;
+ return DEFAULT_DISPLAY;
}
/**
@@ -386,13 +447,6 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
}
/**
- * @return whether notification panel is expanded
- */
- public boolean isNotificationPanelExpanded() {
- return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
- }
-
- /**
* @return whether the global actions dialog is showing
*/
public boolean isSystemUiDialogShowing() {
@@ -544,15 +598,31 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
/**
* Returns the touch slop for {@link InputConsumer}s to compare against before pilfering
- * pointers. Note that this is squared because it expects to be compared against
- * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event).
+ * pointers.
*/
- public float getSquaredTouchSlop() {
+ public float getTouchSlop() {
float slopMultiplier = isFullyGesturalNavMode()
? QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL
: QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON;
float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- return slopMultiplier * touchSlop * touchSlop;
+
+ if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
+ float customSlopMultiplier =
+ LauncherPrefs.get(mContext).get(LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE) / 100f;
+ return customSlopMultiplier * slopMultiplier * touchSlop;
+ } else {
+ return slopMultiplier * touchSlop;
+ }
+ }
+
+ /**
+ * Returns the squared touch slop for {@link InputConsumer}s to compare against before pilfering
+ * pointers. Note that this is squared because it expects to be compared against
+ * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event).
+ */
+ public float getSquaredTouchSlop() {
+ float touchSlop = getTouchSlop();
+ return touchSlop * touchSlop;
}
public String getSystemUiStateString() {