summaryrefslogtreecommitdiffstats
path: root/quickstep
diff options
context:
space:
mode:
Diffstat (limited to 'quickstep')
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java4
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java7
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java1
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java88
-rw-r--r--quickstep/res/values/dimens.xml1
-rw-r--r--quickstep/src/com/android/quickstep/util/MotionPauseDetector.java42
6 files changed, 134 insertions, 9 deletions
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index e20ef5259..2c919b3c1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -296,10 +296,6 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
if (sysUiProxy == null) {
return null;
}
- if (SysUINavigationMode.getMode(activity) == SysUINavigationMode.Mode.NO_BUTTON) {
- // TODO(b/130225926): Temporarily disable pinning while gesture nav is enabled
- return null;
- }
if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
return null;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index cad607423..128fd45fe 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -72,6 +72,7 @@ import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
+import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -466,6 +467,12 @@ public class TouchInteractionService extends Service implements
mInputMonitorCompat);
}
+ if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
+ // Note: we only allow accessibility to wrap this, and it replaces the previous
+ // base input consumer (which should be NO_OP anyway since topTaskLocked == true).
+ base = new ScreenPinnedInputConsumer(this, mISystemUiProxy, activityControl);
+ }
+
if ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0) {
base = new AccessibilityInputConsumer(this, mISystemUiProxy,
(mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0, base,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
index 3593d162d..2e8880dde 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
@@ -30,6 +30,7 @@ public interface InputConsumer {
int TYPE_ASSISTANT = 1 << 3;
int TYPE_DEVICE_LOCKED = 1 << 4;
int TYPE_ACCESSIBILITY = 1 << 5;
+ int TYPE_SCREEN_PINNED = 1 << 6;
InputConsumer NO_OP = () -> TYPE_NO_OP;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
new file mode 100644
index 000000000..a0e20f2cd
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.inputconsumers;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.quickstep.ActivityControlHelper;
+import com.android.quickstep.util.MotionPauseDetector;
+import com.android.systemui.shared.recents.ISystemUiProxy;
+
+/**
+ * An input consumer that detects swipe up and hold to exit screen pinning mode.
+ */
+public class ScreenPinnedInputConsumer implements InputConsumer {
+
+ private static final String TAG = "ScreenPinnedConsumer";
+
+ private final float mMotionPauseMinDisplacement;
+ private final MotionPauseDetector mMotionPauseDetector;
+
+ private float mTouchDownY;
+
+ public ScreenPinnedInputConsumer(Context context, ISystemUiProxy sysuiProxy,
+ ActivityControlHelper activityControl) {
+ mMotionPauseMinDisplacement = context.getResources().getDimension(
+ R.dimen.motion_pause_detector_min_displacement_from_app);
+ mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/);
+ mMotionPauseDetector.setOnMotionPauseListener(isPaused -> {
+ if (isPaused) {
+ try {
+ sysuiProxy.stopScreenPinning();
+ BaseDraggingActivity launcherActivity = activityControl.getCreatedActivity();
+ if (launcherActivity != null) {
+ launcherActivity.getRootView().performHapticFeedback(
+ HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ }
+ mMotionPauseDetector.clear();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to stop screen pinning ", e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public int getType() {
+ return TYPE_SCREEN_PINNED;
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent ev) {
+ float y = ev.getY();
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTouchDownY = y;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ float displacement = mTouchDownY - y;
+ mMotionPauseDetector.setDisallowPause(displacement < mMotionPauseMinDisplacement);
+ mMotionPauseDetector.addPosition(y, ev.getEventTime());
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mMotionPauseDetector.clear();
+ break;
+ }
+ }
+}
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 32f312fdb..82d1aa672 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -36,6 +36,7 @@
<!-- These speeds are in dp / ms -->
<dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
+ <dimen name="motion_pause_detector_speed_slow">0.15dp</dimen>
<dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
<dimen name="motion_pause_detector_speed_fast">0.5dp</dimen>
<dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index f58f0d485..893c05356 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -35,10 +35,18 @@ public class MotionPauseDetector {
/** If no motion is added for this amount of time, assume the motion has paused. */
private static final long FORCE_PAUSE_TIMEOUT = 300;
+ /**
+ * After {@link #makePauseHarderToTrigger()}, must
+ * move slowly for this long to trigger a pause.
+ */
+ private static final long HARDER_TRIGGER_TIMEOUT = 400;
+
private final float mSpeedVerySlow;
+ private final float mSpeedSlow;
private final float mSpeedSomewhatFast;
private final float mSpeedFast;
private final Alarm mForcePauseTimeout;
+ private final boolean mMakePauseHarderToTrigger;
private Long mPreviousTime = null;
private Float mPreviousPosition = null;
@@ -52,19 +60,29 @@ public class MotionPauseDetector {
private boolean mHasEverBeenPaused;
/** @see #setDisallowPause(boolean) */
private boolean mDisallowPause;
+ // Time at which speed became < mSpeedSlow (only used if mMakePauseHarderToTrigger == true).
+ private long mSlowStartTime;
public MotionPauseDetector(Context context) {
+ this(context, false);
+ }
+
+ /**
+ * @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
+ */
+ public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
+ mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
+ mMakePauseHarderToTrigger = makePauseHarderToTrigger;
}
/**
- * Get callbacks for when motion pauses and resumes, including an
- * immediate callback with the current pause state.
+ * Get callbacks for when motion pauses and resumes.
*/
public void setOnMotionPauseListener(OnMotionPauseListener listener) {
mOnMotionPauseListener = listener;
@@ -88,13 +106,15 @@ public class MotionPauseDetector {
if (mFirstPosition == null) {
mFirstPosition = position;
}
- mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
+ mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
+ ? HARDER_TRIGGER_TIMEOUT
+ : FORCE_PAUSE_TIMEOUT);
if (mPreviousTime != null && mPreviousPosition != null) {
long changeInTime = Math.max(1, time - mPreviousTime);
float changeInPosition = position - mPreviousPosition;
float velocity = changeInPosition / changeInTime;
if (mPreviousVelocity != null) {
- checkMotionPaused(velocity, mPreviousVelocity);
+ checkMotionPaused(velocity, mPreviousVelocity, time);
}
mPreviousVelocity = velocity;
}
@@ -102,7 +122,7 @@ public class MotionPauseDetector {
mPreviousPosition = position;
}
- private void checkMotionPaused(float velocity, float prevVelocity) {
+ private void checkMotionPaused(float velocity, float prevVelocity, long time) {
float speed = Math.abs(velocity);
float previousSpeed = Math.abs(prevVelocity);
boolean isPaused;
@@ -122,6 +142,17 @@ public class MotionPauseDetector {
boolean isRapidDeceleration = speed < previousSpeed * RAPID_DECELERATION_FACTOR;
isPaused = isRapidDeceleration && speed < mSpeedSomewhatFast;
}
+ if (mMakePauseHarderToTrigger) {
+ if (speed < mSpeedSlow) {
+ if (mSlowStartTime == 0) {
+ mSlowStartTime = time;
+ }
+ isPaused = time - mSlowStartTime >= HARDER_TRIGGER_TIMEOUT;
+ } else {
+ mSlowStartTime = 0;
+ isPaused = false;
+ }
+ }
}
}
updatePaused(isPaused);
@@ -149,6 +180,7 @@ public class MotionPauseDetector {
mFirstPosition = null;
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
+ mSlowStartTime = 0;
mForcePauseTimeout.cancelAlarm();
}