diff options
Diffstat (limited to 'quickstep')
16 files changed, 387 insertions, 963 deletions
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java index efa83e4b6..1fb3584a2 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java @@ -85,8 +85,8 @@ public class AllAppsState extends LauncherState { } @Override - public float getHoseatAlpha(Launcher launcher) { - return 0; + public int getVisibleElements(Launcher launcher) { + return ALL_APPS_HEADER | ALL_APPS_CONTENT; } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/DragPauseDetector.java b/quickstep/src/com/android/launcher3/uioverrides/DragPauseDetector.java deleted file mode 100644 index 6df1aba01..000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/DragPauseDetector.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2017 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.launcher3.uioverrides; - -import com.android.launcher3.Alarm; -import com.android.launcher3.OnAlarmListener; - -/** - * Utility class to detect a pause during a drag. - */ -public class DragPauseDetector implements OnAlarmListener { - - private static final float MAX_VELOCITY_TO_PAUSE = 0.2f; - private static final long PAUSE_DURATION = 100; - - private final Alarm mAlarm; - private final Runnable mOnPauseCallback; - - private boolean mTriggered = false; - private int mDisabledFlags = 0; - - public DragPauseDetector(Runnable onPauseCallback) { - mOnPauseCallback = onPauseCallback; - - mAlarm = new Alarm(); - mAlarm.setOnAlarmListener(this); - mAlarm.setAlarm(PAUSE_DURATION); - } - - public void onDrag(float velocity) { - if (mTriggered || !isEnabled()) { - return; - } - - if (Math.abs(velocity) > MAX_VELOCITY_TO_PAUSE) { - // Cancel any previous alarm and set a new alarm - mAlarm.setAlarm(PAUSE_DURATION); - } - } - - @Override - public void onAlarm(Alarm alarm) { - if (!mTriggered && isEnabled()) { - mTriggered = true; - mOnPauseCallback.run(); - } - } - - public boolean isTriggered () { - return mTriggered; - } - - public boolean isEnabled() { - return mDisabledFlags == 0; - } - - public void addDisabledFlags(int flags) { - boolean wasEnabled = isEnabled(); - mDisabledFlags |= flags; - resetAlarm(wasEnabled); - } - - public void clearDisabledFlags(int flags) { - boolean wasEnabled = isEnabled(); - mDisabledFlags &= ~flags; - resetAlarm(wasEnabled); - } - - private void resetAlarm(boolean wasEnabled) { - boolean isEnabled = isEnabled(); - if (wasEnabled == isEnabled) { - // Nothing has changed - } if (isEnabled && !mTriggered) { - mAlarm.setAlarm(PAUSE_DURATION); - } else if (!isEnabled) { - mAlarm.cancelAlarm(); - } - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java deleted file mode 100644 index 97ac3e606..000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2018 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.launcher3.uioverrides; - -import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.touch.SwipeDetector.DIRECTION_NEGATIVE; -import static com.android.launcher3.touch.SwipeDetector.DIRECTION_POSITIVE; -import static com.android.launcher3.touch.SwipeDetector.HORIZONTAL; -import static com.android.launcher3.touch.SwipeDetector.VERTICAL; -import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR; - -import android.graphics.Rect; -import android.metrics.LogMaker; -import android.view.MotionEvent; - -import com.android.launcher3.DeviceProfile; -import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; -import com.android.launcher3.dragndrop.DragLayer; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.util.VerticalSwipeController; -import com.android.quickstep.views.RecentsView; - -class EventLogTags { - private EventLogTags() { - } // don't instantiate - - /** 524292 sysui_multi_action (content|4) */ - public static final int SYSUI_MULTI_ACTION = 524292; - - public static void writeSysuiMultiAction(Object[] content) { - android.util.EventLog.writeEvent(SYSUI_MULTI_ACTION, content); - } -} - -class MetricsLogger { - private static MetricsLogger sMetricsLogger; - - private static MetricsLogger getLogger() { - if (sMetricsLogger == null) { - sMetricsLogger = new MetricsLogger(); - } - return sMetricsLogger; - } - - protected void saveLog(Object[] rep) { - EventLogTags.writeSysuiMultiAction(rep); - } - - public void write(LogMaker content) { - if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) { - content.setType(4/*MetricsEvent.TYPE_ACTION*/); - } - saveLog(content.serialize()); - } -} - -/** - * Extension of {@link VerticalSwipeController} to go from NORMAL to OVERVIEW. - */ -public class EdgeSwipeController extends VerticalSwipeController implements - OnDeviceProfileChangeListener { - - private static final Rect sTempRect = new Rect(); - - private final MetricsLogger mMetricsLogger = new MetricsLogger(); - - public EdgeSwipeController(Launcher l) { - super(l, NORMAL, OVERVIEW, l.getDeviceProfile().isVerticalBarLayout() - ? HORIZONTAL : VERTICAL); - l.addOnDeviceProfileChangeListener(this); - } - - @Override - public void onDeviceProfileChanged(DeviceProfile dp) { - mDetector.updateDirection(dp.isVerticalBarLayout() ? HORIZONTAL : VERTICAL); - } - - @Override - protected boolean shouldInterceptTouch(MotionEvent ev) { - return mLauncher.isInState(NORMAL) && (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0; - } - - @Override - protected int getSwipeDirection(MotionEvent ev) { - return isTransitionFlipped() ? DIRECTION_NEGATIVE : DIRECTION_POSITIVE; - } - - public EdgeSwipeController(Launcher l, LauncherState baseState) { - super(l, baseState); - } - - @Override - protected boolean isTransitionFlipped() { - return mLauncher.getDeviceProfile().isSeascape(); - } - - @Override - protected void onTransitionComplete(boolean wasFling, boolean stateChanged) { - if (stateChanged && mToState instanceof OverviewState) { - // Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for - // "Recents" activity for app transition tests. - final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/); - builder.setPackageName("com.android.systemui"); - builder.addTaggedData(871/*FIELD_CLASS_NAME*/, - "com.android.systemui.recents.RecentsActivity"); - builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/, - 0/* zero time */); - mMetricsLogger.write(builder); - - // Add user event logging for launcher pipeline - int direction = Direction.UP; - if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { - direction = Direction.LEFT; - if (mLauncher.getDeviceProfile().isSeascape()) { - direction = Direction.RIGHT; - } - } - mLauncher.getUserEventDispatcher().logStateChangeAction( - wasFling ? Touch.FLING : Touch.SWIPE, direction, - ContainerType.NAVBAR, ContainerType.WORKSPACE, // src target - ContainerType.TASKSWITCHER, // dst target - mLauncher.getWorkspace().getCurrentPage()); - } - } - - @Override - protected float getShiftRange() { - return getShiftRange(mLauncher); - } - - public static float getShiftRange(Launcher launcher) { - RecentsView.getPageRect(launcher.getDeviceProfile(), launcher, sTempRect); - DragLayer dl = launcher.getDragLayer(); - Rect insets = dl.getInsets(); - DeviceProfile dp = launcher.getDeviceProfile(); - - if (dp.isVerticalBarLayout()) { - if (dp.isSeascape()) { - return insets.left + sTempRect.left; - } else { - return dl.getWidth() - sTempRect.right + insets.right; - } - } else { - return dl.getHeight() - sTempRect.bottom + insets.bottom; - } - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java index 9541d0d05..9e82b2571 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java @@ -41,10 +41,10 @@ public class FastOverviewState extends OverviewState { } @Override - public float getHoseatAlpha(Launcher launcher) { + public int getVisibleElements(Launcher launcher) { if (DEBUG_DIFFERENT_UI) { - return 0; + return NONE; } - return super.getHoseatAlpha(launcher); + return super.getVisibleElements(launcher); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java new file mode 100644 index 000000000..23add9595 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java @@ -0,0 +1,71 @@ +package com.android.launcher3.uioverrides; + +import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR; + +import android.view.MotionEvent; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.touch.AbstractStateChangeTouchController; +import com.android.launcher3.touch.SwipeDetector; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; +import com.android.quickstep.util.SysuiEventLogger; + +/** + * Touch controller for handling edge swipes in landscape/seascape UI + */ +public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchController { + + public LandscapeEdgeSwipeController(Launcher l) { + super(l, SwipeDetector.HORIZONTAL); + } + + @Override + protected boolean canInterceptTouch(MotionEvent ev) { + if (mCurrentAnimation != null) { + // If we are already animating from a previous state, we can intercept. + return true; + } + if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { + return false; + } + return mLauncher.isInState(NORMAL) && (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0; + } + + @Override + protected int getSwipeDirection(MotionEvent ev) { + mFromState = NORMAL; + mToState = OVERVIEW; + return SwipeDetector.DIRECTION_BOTH; + } + + @Override + protected float getShiftRange() { + return mLauncher.getDragLayer().getWidth(); + } + + @Override + protected float initCurrentAnimation() { + float range = getShiftRange(); + long maxAccuracy = (long) (2 * range); + mCurrentAnimation = mLauncher.getStateManager() + .createAnimationToNewWorkspace(mToState, maxAccuracy); + return (mLauncher.getDeviceProfile().isSeascape() ? 2 : -2) / range; + } + + @Override + protected int getDirectionForLog() { + return mLauncher.getDeviceProfile().isSeascape() ? Direction.RIGHT : Direction.LEFT; + } + + @Override + protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { + super.onSwipeInteractionCompleted(targetState, logAction); + if (mFromState == NORMAL && targetState == OVERVIEW) { + SysuiEventLogger.writeDummyRecentsTransition(0); + } + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java new file mode 100644 index 000000000..720b20ac1 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 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.launcher3.uioverrides; + +import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; + +import android.view.MotionEvent; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.quickstep.TouchInteractionService; +import com.android.quickstep.views.RecentsView; + +/** + * Touch controller from going from OVERVIEW to ALL_APPS + */ +public class LandscapeStatesTouchController extends PortraitStatesTouchController { + + public LandscapeStatesTouchController(Launcher l) { + super(l); + } + + @Override + protected boolean canInterceptTouch(MotionEvent ev) { + if (mCurrentAnimation != null) { + // If we are already animating from a previous state, we can intercept. + return true; + } + if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { + return false; + } + if (mLauncher.isInState(ALL_APPS)) { + // In all-apps only listen if the container cannot scroll itself + return mLauncher.getAppsView().shouldContainerScroll(ev); + } else if (mLauncher.isInState(NORMAL)) { + return true; + } else if (mLauncher.isInState(OVERVIEW)) { + RecentsView rv = mLauncher.getOverviewPanel(); + return ev.getY() > (rv.getBottom() - rv.getPaddingBottom()); + } else { + return false; + } + } + + protected LauncherState getTargetState() { + if (mLauncher.isInState(ALL_APPS)) { + // Should swipe down go to OVERVIEW instead? + return TouchInteractionService.isConnected() ? + mLauncher.getStateManager().getLastState() : NORMAL; + } else { + return ALL_APPS; + } + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java index 09acb1d2b..d123dce5a 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java @@ -22,6 +22,7 @@ import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE; import android.graphics.Rect; import android.view.View; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Workspace; @@ -105,4 +106,29 @@ public class OverviewState extends LauncherState { return new float[] {scale, 0, translationY}; } + + @Override + public int getVisibleElements(Launcher launcher) { + if (launcher.getDeviceProfile().isVerticalBarLayout()) { + // TODO: Remove hotseat from overview + return HOTSEAT; + } else { + return launcher.getAppsView().getFloatingHeaderView().hasVisibleContent() + ? ALL_APPS_HEADER : HOTSEAT; + } + } + + @Override + public float getVerticalProgress(Launcher launcher) { + if (getVisibleElements(launcher) == HOTSEAT) { + return super.getVerticalProgress(launcher); + } + return 1 - (getDefaultSwipeHeight(launcher) + / launcher.getAllAppsController().getShiftRange()); + } + + public static float getDefaultSwipeHeight(Launcher launcher) { + DeviceProfile dp = launcher.getDeviceProfile(); + return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx; + } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java deleted file mode 100644 index 4fb388613..000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeUpController.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2017 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.launcher3.uioverrides; - -import static com.android.launcher3.LauncherState.OVERVIEW; - -import android.view.MotionEvent; - -import com.android.launcher3.Launcher; -import com.android.launcher3.touch.SwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.util.VerticalSwipeController; - -/** - * Extension of {@link VerticalSwipeController} which allows swipe up from OVERVIEW to ALL_APPS - * Note that the swipe down is handled by {@link TwoStepSwipeController}. - */ -public class OverviewSwipeUpController extends VerticalSwipeController { - - public OverviewSwipeUpController(Launcher l) { - super(l, OVERVIEW); - } - - @Override - protected boolean shouldInterceptTouch(MotionEvent ev) { - if (!mLauncher.isInState(OVERVIEW)) { - return false; - } - if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { - return ev.getY() > - mLauncher.getDragLayer().getHeight() * OVERVIEW.getVerticalProgress(mLauncher); - } else { - return mLauncher.getDragLayer().isEventOverHotseat(ev); - } - } - - @Override - protected int getSwipeDirection(MotionEvent ev) { - return SwipeDetector.DIRECTION_POSITIVE; - } - - @Override - protected void onTransitionComplete(boolean wasFling, boolean stateChanged) { - if (stateChanged) { - // Transition complete. log the action - mLauncher.getUserEventDispatcher().logStateChangeAction( - wasFling ? Touch.FLING : Touch.SWIPE, - Direction.UP, - ContainerType.HOTSEAT, - ContainerType.TASKSWITCHER, - ContainerType.ALLAPPS, - mLauncher.getWorkspace().getCurrentPage()); - } - - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java new file mode 100644 index 000000000..9f648edd1 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 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.launcher3.uioverrides; + +import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; + +import android.view.MotionEvent; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.touch.SwipeDetector; +import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.launcher3.touch.AbstractStateChangeTouchController; +import com.android.quickstep.TouchInteractionService; +import com.android.quickstep.util.SysuiEventLogger; + +/** + * Touch controller for handling various state transitions in portrait UI. + */ +public class PortraitStatesTouchController extends AbstractStateChangeTouchController { + + public PortraitStatesTouchController(Launcher l) { + super(l, SwipeDetector.VERTICAL); + } + + @Override + protected boolean canInterceptTouch(MotionEvent ev) { + if (mCurrentAnimation != null) { + // If we are already animating from a previous state, we can intercept. + return true; + } + if (mLauncher.isInState(ALL_APPS)) { + // In all-apps only listen if the container cannot scroll itself + if (!mLauncher.getAppsView().shouldContainerScroll(ev)) { + return false; + } + } else { + // For all other states, only listen if the event originated below the hotseat height + DeviceProfile dp = mLauncher.getDeviceProfile(); + int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom; + if (ev.getY() < (mLauncher.getDragLayer().getHeight() - hotseatHeight)) { + return false; + } + } + if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { + return false; + } + return true; + } + + @Override + protected int getSwipeDirection(MotionEvent ev) { + final int directionsToDetectScroll; + if (mLauncher.isInState(ALL_APPS)) { + directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE; + mStartContainerType = ContainerType.ALLAPPS; + } else if (mLauncher.isInState(NORMAL)) { + directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; + mStartContainerType = ContainerType.HOTSEAT; + } else if (mLauncher.isInState(OVERVIEW)) { + directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; + mStartContainerType = ContainerType.TASKSWITCHER; + } else { + return 0; + } + mFromState = mLauncher.getStateManager().getState(); + mToState = getTargetState(); + if (mFromState == mToState) { + return 0; + } + return directionsToDetectScroll; + } + + protected LauncherState getTargetState() { + if (mLauncher.isInState(ALL_APPS)) { + // Should swipe down go to OVERVIEW instead? + return TouchInteractionService.isConnected() ? + mLauncher.getStateManager().getLastState() : NORMAL; + } else if (mLauncher.isInState(OVERVIEW)) { + return ALL_APPS; + } else { + return TouchInteractionService.isConnected() ? OVERVIEW : ALL_APPS; + } + } + + @Override + protected float initCurrentAnimation() { + float range = getShiftRange(); + long maxAccuracy = (long) (2 * range); + mCurrentAnimation = mLauncher.getStateManager() + .createAnimationToNewWorkspace(mToState, maxAccuracy); + + float startVerticalShift = mFromState.getVerticalProgress(mLauncher) * range; + float endVerticalShift = mToState.getVerticalProgress(mLauncher) * range; + + float totalShift = endVerticalShift - startVerticalShift; + if (totalShift == 0) { + totalShift = Math.signum(mFromState.ordinal - mToState.ordinal) + * OverviewState.getDefaultSwipeHeight(mLauncher); + } + return 1 / totalShift; + } + + @Override + protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { + super.onSwipeInteractionCompleted(targetState, logAction); + if (mFromState == NORMAL && targetState == OVERVIEW) { + SysuiEventLogger.writeDummyRecentsTransition(0); + } + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaggedAnimatorSetBuilder.java b/quickstep/src/com/android/launcher3/uioverrides/TaggedAnimatorSetBuilder.java deleted file mode 100644 index 651a75354..000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/TaggedAnimatorSetBuilder.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2017 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.launcher3.uioverrides; - -import android.animation.Animator; -import android.util.SparseArray; - -import com.android.launcher3.anim.AnimatorSetBuilder; - -import java.util.Collections; -import java.util.List; - -public class TaggedAnimatorSetBuilder extends AnimatorSetBuilder { - - /** - * Map of the index in {@link #mAnims} to tag. All the animations in {@link #mAnims} starting - * from this index correspond to the tag (until a new tag is specified for an index) - */ - private final SparseArray<Object> mTags = new SparseArray<>(); - - @Override - public void startTag(Object obj) { - mTags.put(mAnims.size(), obj); - } - - public List<Animator> getAnimationsForTag(Object tag) { - int startIndex = mTags.indexOfValue(tag); - if (startIndex < 0) { - return Collections.emptyList(); - } - int startPos = mTags.keyAt(startIndex); - - int endIndex = startIndex + 1; - int endPos = endIndex >= mTags.size() ? mAnims.size() : mTags.keyAt(endIndex); - - return mAnims.subList(startPos, endPos); - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index 8b738091a..d11547de8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -15,8 +15,6 @@ */ package com.android.launcher3.uioverrides; -import static com.android.launcher3.LauncherState.ALL_APPS; -import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; @@ -30,24 +28,21 @@ import android.view.View; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.touch.SwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TouchController; import com.android.quickstep.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; /** - * Touch controller for swipe interaction in Overview state + * Touch controller for handling task view card swipes */ -public class OverviewSwipeController extends AnimatorListenerAdapter +public class TaskViewTouchController extends AnimatorListenerAdapter implements TouchController, SwipeDetector.Listener { private static final String TAG = "OverviewSwipeController"; @@ -68,16 +63,14 @@ public class OverviewSwipeController extends AnimatorListenerAdapter private boolean mCurrentAnimationIsGoingUp; private boolean mNoIntercept; - private boolean mSwipeDownEnabled; private float mDisplacementShift; private float mProgressMultiplier; private float mEndDisplacement; - private int mStartingTarget; private TaskView mTaskBeingDragged; - public OverviewSwipeController(Launcher launcher) { + public TaskViewTouchController(Launcher launcher) { mLauncher = launcher; mRecentsView = launcher.getOverviewPanel(); mDetector = new SwipeDetector(launcher, this, SwipeDetector.VERTICAL); @@ -94,15 +87,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter return mLauncher.isInState(OVERVIEW); } - private boolean isEventOverHotseat(MotionEvent ev) { - if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { - return ev.getY() > - mLauncher.getDragLayer().getHeight() * OVERVIEW.getVerticalProgress(mLauncher); - } else { - return mLauncher.getDragLayer().isEventOverHotseat(ev); - } - } - @Override public void onAnimationCancel(Animator animation) { if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) { @@ -129,22 +113,14 @@ public class OverviewSwipeController extends AnimatorListenerAdapter ignoreSlopWhenSettling = true; } else { mTaskBeingDragged = null; - mSwipeDownEnabled = true; View view = mRecentsView.getChildAt(mRecentsView.getCurrentPage()); if (view instanceof TaskView && mLauncher.getDragLayer().isEventOverView(view, ev)) { // The tile can be dragged down to open the task. mTaskBeingDragged = (TaskView) view; directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; - mStartingTarget = LauncherLogProto.ItemType.TASK; - } else if (isEventOverHotseat(ev)) { - // The hotseat is being dragged - directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; - mSwipeDownEnabled = false; - mStartingTarget = ContainerType.HOTSEAT; } else { mNoIntercept = true; - mStartingTarget = ContainerType.WORKSPACE; return false; } } @@ -167,9 +143,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter } private void reInitAnimationController(boolean goingUp) { - if (!goingUp && !mSwipeDownEnabled) { - goingUp = true; - } if (mCurrentAnimation != null && mCurrentAnimationIsGoingUp == goingUp) { // No need to init return; @@ -187,31 +160,20 @@ public class OverviewSwipeController extends AnimatorListenerAdapter long maxDuration = (long) (2 * range); DragLayer dl = mLauncher.getDragLayer(); - if (mTaskBeingDragged == null) { - // User is either going to all apps or home - mCurrentAnimation = mLauncher.getStateManager() - .createAnimationToNewWorkspace(goingUp ? ALL_APPS : NORMAL, maxDuration); - if (goingUp) { - mEndDisplacement = -range; - } else { - mEndDisplacement = EdgeSwipeController.getShiftRange(mLauncher); - } + if (goingUp) { + mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged, + true /* animateTaskView */, true /* removeTask */, maxDuration); + mCurrentAnimation = AnimatorPlaybackController + .wrap(mPendingAnimation.anim, maxDuration); + mEndDisplacement = -mTaskBeingDragged.getHeight(); } else { - if (goingUp) { - mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged, - true /* animateTaskView */, true /* removeTask */, maxDuration); - mCurrentAnimation = AnimatorPlaybackController - .wrap(mPendingAnimation.anim, maxDuration); - mEndDisplacement = -mTaskBeingDragged.getHeight(); - } else { - AnimatorSet anim = new AnimatorSet(); - // TODO: Setup a zoom animation - mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration); + AnimatorSet anim = new AnimatorSet(); + // TODO: Setup a zoom animation + mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration); - mTempCords[1] = mTaskBeingDragged.getHeight(); - dl.getDescendantCoordRelativeToSelf(mTaskBeingDragged, mTempCords); - mEndDisplacement = dl.getHeight() - mTempCords[1]; - } + mTempCords[1] = mTaskBeingDragged.getHeight(); + dl.getDescendantCoordRelativeToSelf(mTaskBeingDragged, mTempCords); + mEndDisplacement = dl.getHeight() - mTempCords[1]; } mCurrentAnimation.getTarget().addListener(this); @@ -249,9 +211,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter if (fling) { logAction = Touch.FLING; boolean goingUp = velocity < 0; - if (!goingUp && !mSwipeDownEnabled) { - goingToEnd = false; - } else if (goingUp != mCurrentAnimationIsGoingUp) { + if (goingUp != mCurrentAnimationIsGoingUp) { // In case the fling is in opposite direction, make sure if is close enough // from the start position if (mCurrentAnimation.getProgressFraction() @@ -277,7 +237,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter float nextFrameProgress = Utilities.boundToRange( progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f); - mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction)); ValueAnimator anim = mCurrentAnimation.getAnimationPlayer(); @@ -292,25 +251,13 @@ public class OverviewSwipeController extends AnimatorListenerAdapter mPendingAnimation.finish(wasSuccess); mPendingAnimation = null; } - if (mTaskBeingDragged == null) { - LauncherState state = wasSuccess ? - (mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW; - mLauncher.getStateManager().goToState(state, false); - - } else if (wasSuccess) { + if (wasSuccess) { if (!mCurrentAnimationIsGoingUp) { mTaskBeingDragged.launchTask(false); mLauncher.getUserEventDispatcher().logTaskLaunch(logAction, Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent()); } } - if (mTaskBeingDragged == null || (wasSuccess && mCurrentAnimationIsGoingUp)) { - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - mCurrentAnimationIsGoingUp ? Direction.UP : Direction.DOWN, - mStartingTarget, ContainerType.TASKSWITCHER, - mLauncher.getStateManager().getState().containerType, - mRecentsView.getCurrentPage()); - } mDetector.finishedScrolling(); mTaskBeingDragged = null; mCurrentAnimation = null; diff --git a/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java deleted file mode 100644 index c8d75dc6f..000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/TwoStepSwipeController.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (C) 2017 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.launcher3.uioverrides; - -import static com.android.launcher3.LauncherState.ALL_APPS; -import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; -import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.util.Log; -import android.view.MotionEvent; - -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; -import com.android.launcher3.LauncherStateManager; -import com.android.launcher3.LauncherStateManager.AnimationConfig; -import com.android.launcher3.LauncherStateManager.StateHandler; -import com.android.launcher3.Utilities; -import com.android.launcher3.anim.AnimationSuccessListener; -import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.anim.AnimatorSetBuilder; -import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.touch.SwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.util.FloatRange; -import com.android.launcher3.util.TouchController; -import com.android.quickstep.TouchInteractionService; - -/** - * Handles vertical touch gesture on the DragLayer - */ -public class TwoStepSwipeController extends AnimatorListenerAdapter - implements TouchController, SwipeDetector.Listener { - - private static final String TAG = "TwoStepSwipeController"; - - private static final float RECATCH_REJECTION_FRACTION = .0875f; - private static final int SINGLE_FRAME_MS = 16; - private static final long QUICK_SNAP_TO_OVERVIEW_DURATION = 250; - - // Progress after which the transition is assumed to be a success in case user does not fling - private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; - - /** - * Index of the vertical swipe handles in {@link LauncherStateManager#getStateHandlers()}. - */ - private static final int SWIPE_HANDLER_INDEX = 0; - - /** - * Index of various UI handlers in {@link LauncherStateManager#getStateHandlers()} not related - * to vertical swipe. - */ - private static final int OTHER_HANDLERS_START_INDEX = SWIPE_HANDLER_INDEX + 1; - - // Swipe progress range (when starting from NORMAL state) where OVERVIEW state is allowed - private static final float MIN_PROGRESS_TO_OVERVIEW = 0.1f; - private static final float MAX_PROGRESS_TO_OVERVIEW = 0.4f; - - private static final int FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE = 1 << 0; - private static final int FLAG_OVERVIEW_DISABLED_FLING = 1 << 1; - private static final int FLAG_OVERVIEW_DISABLED_CANCEL_STATE = 1 << 2; - private static final int FLAG_OVERVIEW_DISABLED = 1 << 4; - private static final int FLAG_DISABLED_TWO_TARGETS = 1 << 5; - private static final int FLAG_DISABLED_BACK_TARGET = 1 << 6; - - private final Launcher mLauncher; - private final SwipeDetector mDetector; - - private boolean mNoIntercept; - private int mStartContainerType; - - private DragPauseDetector mDragPauseDetector; - private FloatRange mOverviewProgressRange; - private TaggedAnimatorSetBuilder mTaggedAnimatorSetBuilder; - private AnimatorSet mQuickOverviewAnimation; - private boolean mAnimatingToOverview; - private CroppedAnimationController mCroppedAnimationController; - - private AnimatorPlaybackController mCurrentAnimation; - private LauncherState mFromState; - private LauncherState mToState; - - private float mStartProgress; - // Ratio of transition process [0, 1] to drag displacement (px) - private float mProgressMultiplier; - - public TwoStepSwipeController(Launcher l) { - mLauncher = l; - mDetector = new SwipeDetector(l, this, SwipeDetector.VERTICAL); - } - - private boolean canInterceptTouch(MotionEvent ev) { - if (mCurrentAnimation != null) { - // If we are already animating from a previous state, we can intercept. - return true; - } - if (mLauncher.isInState(NORMAL)) { - if ((ev.getEdgeFlags() & EDGE_NAV_BAR) != 0 && - !mLauncher.getDeviceProfile().isVerticalBarLayout()) { - // On normal swipes ignore edge swipes - return false; - } - } else if (mLauncher.isInState(ALL_APPS)) { - if (!mLauncher.getAppsView().shouldContainerScroll(ev)) { - return false; - } - } else { - // Don't listen for the swipe gesture if we are already in some other state. - return false; - } - if (mAnimatingToOverview) { - return false; - } - if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { - return false; - } - - return true; - } - - @Override - public void onAnimationCancel(Animator animation) { - if (mCurrentAnimation != null && animation == mCurrentAnimation.getOriginalTarget()) { - Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception()); - clearState(); - } - } - - @Override - public boolean onControllerInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - mNoIntercept = !canInterceptTouch(ev); - if (mNoIntercept) { - return false; - } - - // Now figure out which direction scroll events the controller will start - // calling the callbacks. - final int directionsToDetectScroll; - boolean ignoreSlopWhenSettling = false; - - if (mCurrentAnimation != null) { - if (mCurrentAnimation.getProgressFraction() > 1 - RECATCH_REJECTION_FRACTION) { - directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; - } else if (mCurrentAnimation.getProgressFraction() < RECATCH_REJECTION_FRACTION ) { - directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE; - } else { - directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; - ignoreSlopWhenSettling = true; - } - } else { - if (mLauncher.isInState(ALL_APPS)) { - directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE; - mStartContainerType = ContainerType.ALLAPPS; - } else { - directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; - mStartContainerType = mLauncher.getDragLayer().isEventOverHotseat(ev) ? - ContainerType.HOTSEAT : ContainerType.WORKSPACE; - } - } - - mDetector.setDetectableScrollConditions( - directionsToDetectScroll, ignoreSlopWhenSettling); - } - - if (mNoIntercept) { - return false; - } - - onControllerTouchEvent(ev); - return mDetector.isDraggingOrSettling(); - } - - @Override - public boolean onControllerTouchEvent(MotionEvent ev) { - return mDetector.onTouchEvent(ev); - } - - @Override - public void onDragStart(boolean start) { - if (mCurrentAnimation == null) { - float range = getShiftRange(); - long maxAccuracy = (long) (2 * range); - - mDragPauseDetector = new DragPauseDetector(this::onDragPauseDetected); - mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE); - if (FeatureFlags.ENABLE_TWO_SWIPE_TARGETS) { - mDragPauseDetector.addDisabledFlags(FLAG_DISABLED_TWO_TARGETS); - } - - mOverviewProgressRange = new FloatRange(); - mOverviewProgressRange.start = mLauncher.isInState(NORMAL) - ? MIN_PROGRESS_TO_OVERVIEW - : 1 - MAX_PROGRESS_TO_OVERVIEW; - mOverviewProgressRange.end = mOverviewProgressRange.start - + MAX_PROGRESS_TO_OVERVIEW - MIN_PROGRESS_TO_OVERVIEW; - - // Build current animation - mFromState = mLauncher.getStateManager().getState(); - mToState = mLauncher.isInState(ALL_APPS) ? NORMAL : ALL_APPS; - - if (mToState == NORMAL && mLauncher.getStateManager().getLastState() == OVERVIEW) { - mToState = OVERVIEW; - mDragPauseDetector.addDisabledFlags(FLAG_DISABLED_BACK_TARGET); - } - - mTaggedAnimatorSetBuilder = new TaggedAnimatorSetBuilder(); - mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace( - mToState, mTaggedAnimatorSetBuilder, maxAccuracy); - - if (!TouchInteractionService.isConnected()) { - mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED); - } - - mCurrentAnimation.getTarget().addListener(this); - mStartProgress = 0; - mProgressMultiplier = (mLauncher.isInState(ALL_APPS) ? 1 : -1) / range; - mCurrentAnimation.dispatchOnStart(); - } else { - mCurrentAnimation.pause(); - mStartProgress = mCurrentAnimation.getProgressFraction(); - - mDragPauseDetector.clearDisabledFlags(FLAG_OVERVIEW_DISABLED_FLING); - updatePauseDetectorRangeFlag(); - } - } - - private float getShiftRange() { - return mLauncher.getAllAppsController().getShiftRange(); - } - - @Override - public boolean onDrag(float displacement, float velocity) { - float deltaProgress = mProgressMultiplier * displacement; - mCurrentAnimation.setPlayFraction(deltaProgress + mStartProgress); - - updatePauseDetectorRangeFlag(); - mDragPauseDetector.onDrag(velocity); - - return true; - } - - private void updatePauseDetectorRangeFlag() { - if (mOverviewProgressRange.contains(mCurrentAnimation.getProgressFraction())) { - mDragPauseDetector.clearDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE); - } else { - mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE); - } - } - - @Override - public void onDragEnd(float velocity, boolean fling) { - mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_FLING); - - final int logAction; - LauncherState targetState; - final float progress = mCurrentAnimation.getProgressFraction(); - - if (fling) { - logAction = Touch.FLING; - targetState = velocity < 0 ? ALL_APPS : mLauncher.getStateManager().getLastState(); - // snap to top or bottom using the release velocity - } else { - logAction = Touch.SWIPE; - targetState = (progress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState; - } - - float endProgress; - - if (mDragPauseDetector.isTriggered() && targetState == NORMAL) { - targetState = OVERVIEW; - endProgress = OVERVIEW.getVerticalProgress(mLauncher); - if (mFromState == NORMAL) { - endProgress = 1 - endProgress; - } - } else if (targetState == mToState) { - endProgress = 1; - } else { - endProgress = 0; - } - - LauncherState targetStateFinal = targetState; - mCurrentAnimation.setEndAction(() -> - onSwipeInteractionCompleted(targetStateFinal, logAction)); - - float nextFrameProgress = Utilities.boundToRange( - progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f); - - ValueAnimator anim = mCurrentAnimation.getAnimationPlayer(); - anim.setFloatValues(nextFrameProgress, endProgress); - anim.setDuration( - SwipeDetector.calculateDuration(velocity, Math.abs(endProgress - progress))); - anim.setInterpolator(scrollInterpolatorForVelocity(velocity)); - anim.start(); - } - - private void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { - if (targetState != mFromState) { - // Transition complete. log the action - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - mToState == ALL_APPS ? Direction.UP : Direction.DOWN, - mStartContainerType, - mFromState.containerType, - mToState.containerType, - mLauncher.getWorkspace().getCurrentPage()); - } - clearState(); - - // TODO: mQuickOverviewAnimation might still be running in which changing a state instantly - // may cause a jump. Animate the state change with a short duration in this case? - mLauncher.getStateManager().goToState(targetState, false /* animated */); - } - - private void onDragPauseDetected() { - final ValueAnimator twoStepAnimator = ValueAnimator.ofFloat(0, 1); - twoStepAnimator.setDuration(mCurrentAnimation.getDuration()); - StateHandler[] handlers = mLauncher.getStateManager().getStateHandlers(); - - // Change the current animation to only play the vertical handle - AnimatorSet anim = new AnimatorSet(); - anim.playTogether(mTaggedAnimatorSetBuilder.getAnimationsForTag( - handlers[SWIPE_HANDLER_INDEX])); - anim.play(twoStepAnimator); - mCurrentAnimation = mCurrentAnimation.cloneFor(anim); - - AnimatorSetBuilder builder = new AnimatorSetBuilder(); - AnimationConfig config = new AnimationConfig(); - config.duration = QUICK_SNAP_TO_OVERVIEW_DURATION; - for (int i = OTHER_HANDLERS_START_INDEX; i < handlers.length; i++) { - handlers[i].setStateWithAnimation(OVERVIEW, builder, config); - } - mQuickOverviewAnimation = builder.build(); - mQuickOverviewAnimation.addListener(new AnimationSuccessListener() { - @Override - public void onAnimationSuccess(Animator animator) { - onQuickOverviewAnimationComplete(twoStepAnimator); - } - }); - mQuickOverviewAnimation.start(); - } - - private void onQuickOverviewAnimationComplete(ValueAnimator animator) { - if (mAnimatingToOverview) { - return; - } - - // For the remainder to the interaction, the user can either go to the ALL_APPS state or - // the OVERVIEW state. - // The remaining state handlers are on the OVERVIEW state. Create one animation towards the - // ALL_APPS state and only call it when the user moved above the current range. - AnimationConfig config = new AnimationConfig(); - config.duration = (long) (2 * getShiftRange()); - config.userControlled = true; - - AnimatorSetBuilder builderToAllAppsState = new AnimatorSetBuilder(); - StateHandler[] handlers = mLauncher.getStateManager().getStateHandlers(); - for (int i = OTHER_HANDLERS_START_INDEX; i < handlers.length; i++) { - handlers[i].setStateWithAnimation(ALL_APPS, builderToAllAppsState, config); - } - - mCroppedAnimationController = new CroppedAnimationController( - AnimatorPlaybackController.wrap(builderToAllAppsState.build(), config.duration), - new FloatRange(animator.getAnimatedFraction(), mToState == ALL_APPS ? 1 : 0)); - animator.addUpdateListener(mCroppedAnimationController); - } - - private void clearState() { - mCurrentAnimation = null; - mTaggedAnimatorSetBuilder = null; - if (mDragPauseDetector != null) { - mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_CANCEL_STATE); - } - mDragPauseDetector = null; - - if (mQuickOverviewAnimation != null) { - mQuickOverviewAnimation.cancel(); - mQuickOverviewAnimation = null; - } - mCroppedAnimationController = null; - mAnimatingToOverview = false; - - mDetector.finishedScrolling(); - } - - /** - * {@link AnimatorUpdateListener} which controls another animation for a fraction of range - */ - private static class CroppedAnimationController implements AnimatorUpdateListener { - - private final AnimatorPlaybackController mTarget; - private final FloatRange mRange; - - CroppedAnimationController(AnimatorPlaybackController target, FloatRange range) { - mTarget = target; - mRange = range; - } - - - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - float fraction = valueAnimator.getAnimatedFraction(); - - if (mRange.start < mRange.end) { - if (fraction <= mRange.start) { - mTarget.setPlayFraction(0); - } else if (fraction >= mRange.end) { - mTarget.setPlayFraction(1); - } else { - mTarget.setPlayFraction((fraction - mRange.start) / (mRange.end - mRange.start)); - } - } else if (mRange.start > mRange.end) { - if (fraction >= mRange.start) { - mTarget.setPlayFraction(0); - } else if (fraction <= mRange.end) { - mTarget.setPlayFraction(1); - } else { - mTarget.setPlayFraction((fraction - mRange.start) / (mRange.end - mRange.start)); - } - } else { - // mRange.start == mRange.end - mTarget.setPlayFraction(0); - } - } - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index 637ce60a2..49792ac25 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -25,7 +25,6 @@ import android.view.View.AccessibilityDelegate; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherStateManager.StateHandler; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.util.TouchController; import com.android.quickstep.OverviewInteractionState; @@ -35,17 +34,17 @@ import com.android.quickstep.views.RecentsView; public class UiFactory { public static TouchController[] createTouchControllers(Launcher launcher) { - if (FeatureFlags.ENABLE_TWO_SWIPE_TARGETS) { + if (launcher.getDeviceProfile().isVerticalBarLayout()) { return new TouchController[] { launcher.getDragController(), - new EdgeSwipeController(launcher), - new TwoStepSwipeController(launcher), - new OverviewSwipeController(launcher)}; + new LandscapeStatesTouchController(launcher), + new LandscapeEdgeSwipeController(launcher), + new TaskViewTouchController(launcher)}; } else { return new TouchController[] { launcher.getDragController(), - new TwoStepSwipeController(launcher), - new OverviewSwipeController(launcher)}; + new PortraitStatesTouchController(launcher), + new TaskViewTouchController(launcher)}; } } diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index a9da4f916..b43352a04 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -143,10 +143,13 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> { activity.getStateManager().setRestState(startState); if (!activityVisible) { + // Since the launcher is not visible, we can safely reset the scroll position. + // This ensures then the next swipe up to all-apps starts from scroll 0. + activity.getAppsView().reset(false /* animate */); activity.getStateManager().goToState(OVERVIEW, false); // Optimization, hide the all apps view to prevent layout while initializing - activity.getAppsView().setVisibility(View.GONE); + activity.getAppsView().getContentView().setVisibility(View.GONE); } } @@ -160,20 +163,21 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> { @Override public AnimatorPlaybackController createControllerForHiddenActivity( Launcher activity, int transitionLength) { - float startProgress; AllAppsTransitionController controller = activity.getAllAppsController(); - + AnimatorSet anim = new AnimatorSet(); if (activity.getDeviceProfile().isVerticalBarLayout()) { - startProgress = 1; + // TODO: } else { float scrollRange = Math.max(controller.getShiftRange(), 1); - startProgress = (transitionLength / scrollRange) + 1; + float progressDelta = (transitionLength / scrollRange); + + float endProgress = OVERVIEW.getVerticalProgress(activity); + float startProgress = endProgress + progressDelta; + ObjectAnimator shiftAnim = ObjectAnimator.ofFloat( + controller, ALL_APPS_PROGRESS, startProgress, endProgress); + shiftAnim.setInterpolator(LINEAR); + anim.play(shiftAnim); } - AnimatorSet anim = new AnimatorSet(); - ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(controller, ALL_APPS_PROGRESS, - startProgress, OVERVIEW.getVerticalProgress(activity)); - shiftAnim.setInterpolator(LINEAR); - anim.play(shiftAnim); // TODO: Link this animation to state animation, so that it is cancelled // automatically on state change diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 96cd4a024..2d2a483b5 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -35,7 +35,6 @@ import android.graphics.Matrix.ScaleToFit; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; -import android.metrics.LogMaker; import android.os.Build; import android.os.Handler; import android.os.Looper; @@ -64,6 +63,7 @@ import com.android.launcher3.util.TraceHelper; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.TouchConsumer.InteractionType; +import com.android.quickstep.util.SysuiEventLogger; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -77,40 +77,6 @@ import com.android.systemui.shared.system.WindowManagerWrapper; import java.util.StringJoiner; -class EventLogTags { - private EventLogTags() { - } // don't instantiate - - /** 524292 sysui_multi_action (content|4) */ - public static final int SYSUI_MULTI_ACTION = 524292; - - public static void writeSysuiMultiAction(Object[] content) { - android.util.EventLog.writeEvent(SYSUI_MULTI_ACTION, content); - } -} - -class MetricsLogger { - private static MetricsLogger sMetricsLogger; - - private static MetricsLogger getLogger() { - if (sMetricsLogger == null) { - sMetricsLogger = new MetricsLogger(); - } - return sMetricsLogger; - } - - protected void saveLog(Object[] rep) { - EventLogTags.writeSysuiMultiAction(rep); - } - - public void write(LogMaker content) { - if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) { - content.setType(4/*MetricsEvent.TYPE_ACTION*/); - } - saveLog(content.serialize()); - } -} - @TargetApi(Build.VERSION_CODES.O) public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName(); @@ -229,7 +195,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private Matrix mTmpMatrix = new Matrix(); private final long mTouchTimeMs; private long mLauncherFrameDrawnTime; - private final MetricsLogger mMetricsLogger = new MetricsLogger(); WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, ActivityControlHelper<T> controller) { @@ -453,15 +418,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { onLauncherLayoutChanged(); final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs; - // Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for - // "Recents" activity for app transition tests for the app-to-recents case. - final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/); - builder.setPackageName("com.android.systemui"); - builder.addTaggedData(871/*FIELD_CLASS_NAME*/, - "com.android.systemui.recents.RecentsActivity"); - builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/, - transitionDelay); - mMetricsLogger.write(builder); + SysuiEventLogger.writeDummyRecentsTransition(transitionDelay); + if (LatencyTrackerCompat.isEnabled(mContext)) { LatencyTrackerCompat.logToggleRecents((int) transitionDelay); } diff --git a/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java b/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java new file mode 100644 index 000000000..d474ded90 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 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.util; + +import android.metrics.LogMaker; +import android.util.EventLog; + +/** + * Utility class for writing logs on behalf of systemUI + */ +public class SysuiEventLogger { + + /** 524292 sysui_multi_action (content|4) */ + public static final int SYSUI_MULTI_ACTION = 524292; + + private static void write(LogMaker content) { + if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) { + content.setType(4/*MetricsEvent.TYPE_ACTION*/); + } + EventLog.writeEvent(SYSUI_MULTI_ACTION, content.serialize()); + } + + public static void writeDummyRecentsTransition(long transitionDelay) { + // Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for + // "Recents" activity for app transition tests for the app-to-recents case. + final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/); + builder.setPackageName("com.android.systemui"); + builder.addTaggedData(871/*FIELD_CLASS_NAME*/, + "com.android.systemui.recents.RecentsActivity"); + builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/, + transitionDelay); + write(builder); + } +} |