Merge "Add ScreenPinnedInputConsumer" into ub-launcher3-qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
693c5f5287
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+1
@@ -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;
|
||||
|
||||
|
||||
+88
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user