diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 1042c60b88..eac4dce180 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -121,12 +121,16 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti alpha.setDuration(CONTENT_ALPHA_DURATION); alpha.setInterpolator(LINEAR); anim.play(alpha); + overview.setFreezeViewVisibility(true); ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans); transY.setInterpolator(AGGRESSIVE_EASE); transY.setDuration(CONTENT_TRANSLATION_DURATION); anim.play(transY); - return mLauncher.getStateManager()::reapplyState; + return () -> { + overview.setFreezeViewVisibility(false); + mLauncher.getStateManager().reapplyState(); + }; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java index 336cdc93fe..d84362c9f2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java @@ -204,15 +204,6 @@ public abstract class RecentsUiFactory { } } - /** - * Clean-up logic that occurs when recents is no longer in use/visible. - * - * @param launcher the launcher activity - */ - public static void resetOverview(Launcher launcher) { - launcher.getOverviewPanel().reset(); - } - /** * Recents logic that triggers when launcher state changes or launcher activity stops/resumes. * diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 1d36d1aae8..b5d84247a8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -32,7 +32,6 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager.AnimationConfig; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.PropertySetter; -import com.android.quickstep.hints.ProactiveHintsContainer; import com.android.quickstep.views.ClearAllButton; import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.RecentsView; @@ -55,14 +54,6 @@ public final class RecentsViewStateController extends if (state.overviewUi) { mRecentsView.updateEmptyMessage(); mRecentsView.resetTaskVisuals(); - mRecentsView.setHintVisibility(1f); - } else { - mRecentsView.setHintVisibility(0f); - ProactiveHintsContainer - proactiveHintsContainer = mRecentsView.getProactiveHintsContainer(); - if (proactiveHintsContainer != null) { - proactiveHintsContainer.removeAllViews(); - } } setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher)); mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress()); @@ -75,14 +66,6 @@ public final class RecentsViewStateController extends if (!toState.overviewUi) { builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals); - mRecentsView.setHintVisibility(0f); - builder.addOnFinishRunnable(() -> { - ProactiveHintsContainer - proactiveHintsContainer = mRecentsView.getProactiveHintsContainer(); - if (proactiveHintsContainer != null) { - proactiveHintsContainer.removeAllViews(); - } - }); } if (toState.overviewUi) { @@ -94,7 +77,6 @@ public final class RecentsViewStateController extends updateAnim.setDuration(config.duration); builder.play(updateAnim); mRecentsView.updateEmptyMessage(); - builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1f)); } PropertySetter propertySetter = config.getPropertySetter(builder); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index 8436fe5f9d..f1d6450a5f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -21,7 +21,6 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -45,8 +44,6 @@ public class BackgroundAppState extends OverviewState { @Override public void onStateEnabled(Launcher launcher) { - RecentsView rv = launcher.getOverviewPanel(); - rv.setOverviewStateEnabled(true); AbstractFloatingView.closeAllOpenViews(launcher, false); } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java index cda03dcde1..9a99c15522 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -86,17 +86,9 @@ public class OverviewState extends LauncherState { @Override public void onStateEnabled(Launcher launcher) { - RecentsView rv = launcher.getOverviewPanel(); - rv.setOverviewStateEnabled(true); AbstractFloatingView.closeAllOpenViews(launcher); } - @Override - public void onStateDisabled(Launcher launcher) { - RecentsView rv = launcher.getOverviewPanel(); - rv.setOverviewStateEnabled(false); - } - @Override public void onStateTransitionEnd(Launcher launcher) { launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index a6c4445619..d66af1ae24 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -98,9 +98,6 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect if (mStartState == OVERVIEW || mStartState == ALL_APPS) { return true; } - if (!mLauncher.hasWindowFocus()) { - return true; - } if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { return true; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java index dc58a4efc9..2c42fd63a6 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -17,6 +17,7 @@ package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; +import static com.android.quickstep.fallback.FallbackRecentsView.ZOOM_PROGRESS; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import android.animation.Animator; @@ -33,6 +34,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.RecentsView; @@ -120,11 +122,14 @@ public final class FallbackActivityControllerHelper implements return (transitionLength) -> { }; } - RecentsView rv = activity.getOverviewPanel(); + FallbackRecentsView rv = activity.getOverviewPanel(); rv.setContentAlpha(0); rv.getClearAllButton().setVisibilityAlpha(0); rv.setDisallowScrollToClearAll(true); + boolean fromState = !animateActivity; + rv.setInOverviewState(fromState); + return new AnimationFactory() { boolean isAnimatingToRecents = false; @@ -141,15 +146,28 @@ public final class FallbackActivityControllerHelper implements @Override public void createActivityController(long transitionLength) { - if (!isAnimatingToRecents) { - return; + AnimatorSet animatorSet = new AnimatorSet(); + if (isAnimatingToRecents) { + ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1); + anim.setDuration(transitionLength).setInterpolator(LINEAR); + animatorSet.play(anim); } - ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1); + ObjectAnimator anim = ObjectAnimator.ofFloat(rv, ZOOM_PROGRESS, 1, 0); anim.setDuration(transitionLength).setInterpolator(LINEAR); - AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(anim); - callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength)); + + AnimatorPlaybackController controller = + AnimatorPlaybackController.wrap(animatorSet, transitionLength); + + // Since we are changing the start position of the UI, reapply the state, at the end + controller.setEndAction(() -> { + boolean endState = true; + rv.setInOverviewState(controller.getInterpolatedProgress() > 0.5 ? + endState : fromState); + }); + + callback.accept(controller); } }; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index d0a41f3b53..1b82bcb578 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -36,6 +36,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.os.UserHandle; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.Interpolator; @@ -53,6 +54,7 @@ import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.SpringObjectAnimator; import com.android.launcher3.compat.AccessibilityManagerCompat; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.SysUINavigationMode.Mode; @@ -174,6 +176,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe @Override public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible, boolean animateActivity, Consumer callback) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "prepareRecentsUI"); + } final LauncherState startState = activity.getStateManager().getState(); LauncherState resetState = startState; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java index 5decc3ed6c..32a92618ae 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java @@ -125,7 +125,14 @@ public final class RecentsActivity extends BaseRecentsActivity { @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { - result.setAnimation(composeRecentsLaunchAnimator(taskView, targetCompats)); + AnimatorSet anim = composeRecentsLaunchAnimator(taskView, targetCompats); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mFallbackRecentsView.resetViewUI(); + } + }); + result.setAnimation(anim); } }; return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 84af109a3b..5104fb8801 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -36,8 +36,6 @@ import java.util.List; */ public class TaskOverlayFactory implements ResourceBasedOverride { - public static final String AIAI_PACKAGE = "com.google.android.as"; - /** Note that these will be shown in order from top to bottom, if available for the task. */ private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[]{ new TaskSystemShortcut.AppInfo(), @@ -51,29 +49,33 @@ public class TaskOverlayFactory implements ResourceBasedOverride { new MainThreadInitializedObject<>(c -> Overrides.getObject(TaskOverlayFactory.class, c, R.string.task_overlay_factory_class)); + public List getEnabledShortcuts(TaskView taskView) { + final ArrayList shortcuts = new ArrayList<>(); + final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext()); + for (TaskSystemShortcut menuOption : MENU_OPTIONS) { + View.OnClickListener onClickListener = + menuOption.getOnClickListener(activity, taskView); + if (onClickListener != null) { + shortcuts.add(menuOption); + } + } + return shortcuts; + } + public TaskOverlay createOverlay(View thumbnailView) { return new TaskOverlay(); } public static class TaskOverlay { - public void setTaskInfo(Task task, ThumbnailData thumbnail, Matrix matrix) { - } + /** + * Called when the current task is interactive for the user + */ + public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) { } - public void reset() { - } - - public List getEnabledShortcuts(TaskView taskView) { - final ArrayList shortcuts = new ArrayList<>(); - final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext()); - for (TaskSystemShortcut menuOption : MENU_OPTIONS) { - View.OnClickListener onClickListener = - menuOption.getOnClickListener(activity, taskView); - if (onClickListener != null) { - shortcuts.add(menuOption); - } - } - return shortcuts; - } + /** + * Called when the overlay is no longer used. + */ + public void reset() { } } } 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 294a997f3d..dc354404af 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -27,6 +27,8 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; import android.annotation.TargetApi; import android.app.ActivityManager; @@ -60,6 +62,7 @@ import android.view.WindowManager; import androidx.annotation.BinderThread; +import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; import com.android.launcher3.ResourceUtils; @@ -77,6 +80,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.OverviewWithoutFocusInputConsumer; import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -543,9 +547,11 @@ public class TouchInteractionService extends Service implements if (!useSharedState) { mSwipeSharedState.clearAllState(); } - if (mKM.isDeviceLocked()) { + if ((mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0 + || mKM.isDeviceLocked()) { // This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched - // while device is locked even after exiting direct boot mode (e.g. camera). + // while device is locked after exiting direct boot mode (e.g. camera), or if the + // app is showing over the lockscreen (even if not locked) return createDeviceLockedInputConsumer(runningTaskInfo); } @@ -562,10 +568,9 @@ public class TouchInteractionService extends Service implements info.id = mSwipeSharedState.nextRunningTaskId; return createOtherActivityInputConsumer(event, info); } else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) { - return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false); - } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && - activityControl.isInLiveTileMode()) { - return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false); + return createOverviewInputConsumer(event); + } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) { + return createOverviewInputConsumer(event); } else if (mGestureBlockingActivity != null && runningTaskInfo != null && mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) { return InputConsumer.NO_OP; @@ -574,20 +579,24 @@ public class TouchInteractionService extends Service implements } } + private boolean disableHorizontalSwipe(MotionEvent event) { + // mExclusionRegion can change on binder thread, use a local instance here. + Region exclusionRegion = mExclusionRegion; + return mMode == Mode.NO_BUTTON && exclusionRegion != null + && exclusionRegion.contains((int) event.getX(), (int) event.getY()); + } + private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event, RunningTaskInfo runningTaskInfo) { final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event); - // mExclusionRegion can change on binder thread, use a local instance here. - Region exclusionRegion = mExclusionRegion; - boolean disableHorizontalSwipe = mMode == Mode.NO_BUTTON && exclusionRegion != null - && exclusionRegion.contains((int) event.getX(), (int) event.getY()); return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel, mOverviewComponentObserver.getOverviewIntent(), activityControl, shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive, - mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, disableHorizontalSwipe); + mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, + disableHorizontalSwipe(event)); } private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) { @@ -599,6 +608,23 @@ public class TouchInteractionService extends Service implements } } + public InputConsumer createOverviewInputConsumer(MotionEvent event) { + final ActivityControlHelper activityControl = + mOverviewComponentObserver.getActivityControlHelper(); + BaseDraggingActivity activity = activityControl.getCreatedActivity(); + if (activity == null) { + return InputConsumer.NO_OP; + } + + if (activity.getRootView().hasWindowFocus()) { + return new OverviewInputConsumer(activity, mInputMonitorCompat, + false /* startingInActivityBounds */); + } else { + return new OverviewWithoutFocusInputConsumer(this, mInputMonitorCompat, + disableHorizontalSwipe(event)); + } + } + /** * To be called by the consumer when it's no longer active. */ diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 87b7326648..c7841d98e3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -59,6 +59,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; +import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; @@ -83,6 +84,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.testing.TestProtocol; 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; @@ -267,6 +269,7 @@ public class WindowTransformSwipeHandler private MultiStateCallback mStateCallback; // Used to control launcher components throughout the swipe gesture. private AnimatorPlaybackController mLauncherTransitionController; + private boolean mHasLauncherTransitionControllerStarted; private T mActivity; private RecentsView mRecentsView; @@ -457,17 +460,32 @@ public class WindowTransformSwipeHandler } private void onLauncherStart(final T activity) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart"); + } if (mActivity != activity) { return; } + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 1"); + } if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { return; } + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 2"); + } // If we've already ended the gesture and are going home, don't prepare recents UI, // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. if (mGestureEndTarget != HOME) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 3"); + } Runnable initAnimFactory = () -> { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 4"); + } mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible, true, this::onAnimatorPlaybackControllerCreated); @@ -477,8 +495,14 @@ public class WindowTransformSwipeHandler // Launcher is visible, but might be about to stop. Thus, if we prepare recents // now, it might get overridden by moveToRestState() in onStop(). To avoid this, // wait until the next gesture (and possibly launcher) starts. + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 5"); + } mStateCallback.addCallback(STATE_GESTURE_STARTED, initAnimFactory); } else { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 6"); + } initAnimFactory.run(); } } @@ -647,8 +671,7 @@ public class WindowTransformSwipeHandler } private void buildAnimationController() { - if (mGestureEndTarget == HOME || (mLauncherTransitionController != null - && mLauncherTransitionController.getAnimationPlayer().isStarted())) { + if (mGestureEndTarget == HOME || mHasLauncherTransitionControllerStarted) { // We don't want a new mLauncherTransitionController if mGestureEndTarget == HOME (it // has its own animation) or if we're already animating the current controller. return; @@ -858,7 +881,9 @@ public class WindowTransformSwipeHandler setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha); } - return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true); + BaseDraggingActivity activity = mActivityControlHelper.getCreatedActivity(); + return activity == null + ? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true); } private void endRunningWindowAnim() { @@ -1122,6 +1147,7 @@ public class WindowTransformSwipeHandler } mLauncherTransitionController.getAnimationPlayer().start(); } + mHasLauncherTransitionControllerStarted = true; } /** diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java index e254e240aa..c28761804b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -15,19 +15,45 @@ */ package com.android.quickstep.fallback; +import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.FloatProperty; import android.view.View; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.LauncherState.ScaleAndTranslation; +import com.android.launcher3.Utilities; import com.android.quickstep.RecentsActivity; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskView; public class FallbackRecentsView extends RecentsView { + public static final FloatProperty ZOOM_PROGRESS = + new FloatProperty ("zoomInProgress") { + + @Override + public void setValue(FallbackRecentsView view, float value) { + view.setZoomProgress(value); + } + + @Override + public Float get(FallbackRecentsView view) { + return view.mZoomInProgress; + } + }; + + private float mZoomInProgress = 0; + private boolean mInOverviewState = true; + + private float mZoomScale = 1f; + private float mZoomTranslationY = 0f; + public FallbackRecentsView(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -35,6 +61,7 @@ public class FallbackRecentsView extends RecentsView { public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOverviewStateEnabled(true); + setOverlayEnabled(true); } @Override @@ -70,4 +97,46 @@ public class FallbackRecentsView extends RecentsView { // Just use the activity task size for multi-window as well. return false; } + + public void resetViewUI() { + setZoomProgress(0); + resetTaskVisuals(); + } + + public void setInOverviewState(boolean inOverviewState) { + if (mInOverviewState != inOverviewState) { + mInOverviewState = inOverviewState; + if (mInOverviewState) { + resetTaskVisuals(); + } else { + setZoomProgress(1); + } + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (getTaskViewCount() == 0) { + mZoomScale = 1f; + mZoomTranslationY = 0f; + } else { + TaskView dummyTask = getTaskViewAt(0); + ScaleAndTranslation sat = getTempClipAnimationHelper() + .updateForFullscreenOverview(dummyTask) + .getScaleAndTranslation(); + mZoomScale = sat.scale; + mZoomTranslationY = sat.translationY; + } + + setZoomProgress(mZoomInProgress); + } + + public void setZoomProgress(float progress) { + mZoomInProgress = progress; + SCALE_PROPERTY.set(this, Utilities.mapRange(mZoomInProgress, 1, mZoomScale)); + TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY)); + FULLSCREEN_PROGRESS.set(this, mZoomInProgress); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java deleted file mode 100644 index f2d40ecc4d..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.hints; - -import android.app.PendingIntent; -import android.graphics.drawable.Icon; -import android.os.Bundle; - -public final class HintUtil { - - public static final String ID_KEY = "id"; - public static final String ICON_KEY = "icon"; - public static final String TEXT_KEY = "text"; - public static final String TAP_ACTION_KEY = "tap_action"; - - private HintUtil() {} - - public static Bundle makeHint(String id, Icon icon, CharSequence text) { - Bundle hint = new Bundle(); - hint.putString(ID_KEY, id); - hint.putParcelable(ICON_KEY, icon); - hint.putCharSequence(TEXT_KEY, text); - return hint; - } - - public static Bundle makeHint(Icon icon, CharSequence text, PendingIntent tapAction) { - Bundle hint = new Bundle(); - hint.putParcelable(ICON_KEY, icon); - hint.putCharSequence(TEXT_KEY, text); - hint.putParcelable(TAP_ACTION_KEY, tapAction); - return hint; - } - - public static String getId(Bundle hint) { - String id = hint.getString(ID_KEY); - if (id == null) { - throw new IllegalArgumentException("Hint does not contain an ID"); - } - return id; - } - - public static Icon getIcon(Bundle hint) { - Icon icon = hint.getParcelable(ICON_KEY); - if (icon == null) { - throw new IllegalArgumentException("Hint does not contain an icon"); - } - return icon; - } - - public static CharSequence getText(Bundle hint) { - CharSequence text = hint.getCharSequence(TEXT_KEY); - if (text == null) { - throw new IllegalArgumentException("Hint does not contain text"); - } - return text; - } - - public static PendingIntent getTapAction(Bundle hint) { - PendingIntent tapAction = hint.getParcelable(TAP_ACTION_KEY); - if (tapAction == null) { - throw new IllegalArgumentException("Hint does not contain a tap action"); - } - return tapAction; - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java deleted file mode 100644 index 5399cc4efc..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.hints; - -import static com.android.quickstep.hints.HintUtil.getIcon; -import static com.android.quickstep.hints.HintUtil.getText; - -import android.content.Context; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.util.AttributeSet; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.Nullable; - -import com.android.launcher3.R; - -public class HintView extends LinearLayout { - private ImageView mIconView; - private TextView mLabelView; - - public HintView(Context context) { - super(context); - } - - public HintView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public HintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public HintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void setHint(Bundle hint) { - mLabelView.setText(getText(hint)); - - Icon icon = getIcon(hint); - if (icon == null) { - mIconView.setVisibility(GONE); - } else { - mIconView.setImageIcon(icon); - mIconView.setVisibility(VISIBLE); - } - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mIconView = findViewById(R.id.icon); - mLabelView = findViewById(R.id.label); - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java deleted file mode 100644 index 74a48517b2..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.android.quickstep.hints; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.FloatProperty; -import android.view.View; -import android.widget.FrameLayout; - -public class ProactiveHintsContainer extends FrameLayout { - - public static final FloatProperty HINT_VISIBILITY = - new FloatProperty("hint_visibility") { - @Override - public void setValue(ProactiveHintsContainer proactiveHintsContainer, float v) { - proactiveHintsContainer.setHintVisibility(v); - } - - @Override - public Float get(ProactiveHintsContainer proactiveHintsContainer) { - return proactiveHintsContainer.mHintVisibility; - } - }; - - private float mHintVisibility; - - public ProactiveHintsContainer(Context context) { - super(context); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void setView(View v) { - removeAllViews(); - addView(v); - } - - public void setHintVisibility(float v) { - if (v == 1) { - setVisibility(VISIBLE); - } else { - setVisibility(GONE); - } - mHintVisibility = v; - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java deleted file mode 100644 index 420033dd61..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.hints; - -public final class UiHintListenerConstants { - - private UiHintListenerConstants() {} - - // Operations - public static final int ON_HINTS_RETURNED_CODE = 5; - - // Keys - public static final String SESSION_ID_KEY = "session_id"; - public static final String HINTS_KEY = "hints"; -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java deleted file mode 100644 index 01406130fb..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.hints; - -public final class UiInterfaceConstants { - - private UiInterfaceConstants() {} - - // Operations - public static final int ON_HINT_TAP_CODE = 4; - - public static final int REQUEST_HINTS_CODE = 7; - - // Keys - public static final String SESSION_ID_KEY = "session_id"; - public static final String HINT_ID_KEY = "hint_id"; - public static final String WIDTH_PX_KEY = "width_px"; - public static final String HEIGHT_PX_KEY = "height_px"; - public static final String HINT_SPACE_WIDTH_PX_KEY = "hint_space_width_px"; - public static final String HINT_SPACE_HEIGHT_PX_KEY = "hint_space_height_px"; -} 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 6e7cb8fca8..489eb278fd 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 @@ -31,6 +31,7 @@ public interface InputConsumer { int TYPE_DEVICE_LOCKED = 1 << 4; int TYPE_ACCESSIBILITY = 1 << 5; int TYPE_SCREEN_PINNED = 1 << 6; + int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7; InputConsumer NO_OP = () -> TYPE_NO_OP; @@ -78,6 +79,8 @@ public interface InputConsumer { return "ACCESSIBILITY"; case TYPE_SCREEN_PINNED: return "SCREEN_PINNED"; + case TYPE_OVERVIEW_WITHOUT_FOCUS: + return "TYPE_OVERVIEW_WITHOUT_FOCUS"; default: return "NO_OP"; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index 0ed4c99a6f..69b25db8f5 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -28,7 +28,6 @@ import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSC import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; -import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; @@ -43,10 +42,8 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.view.MotionEvent; -import android.view.Surface; import android.view.VelocityTracker; import android.view.ViewConfiguration; -import android.view.WindowManager; import androidx.annotation.UiThread; @@ -65,6 +62,7 @@ import com.android.quickstep.WindowTransformSwipeHandler; import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget; import com.android.quickstep.util.CachedEventDispatcher; import com.android.quickstep.util.MotionPauseDetector; +import com.android.quickstep.util.NavBarPosition; import com.android.quickstep.util.RecentsAnimationListenerSet; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.BackgroundExecutor; @@ -95,7 +93,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC private final SysUINavigationMode.Mode mMode; private final RectF mSwipeTouchRegion; - private final int mDisplayRotation; + private final NavBarPosition mNavBarPosition; private final Consumer mOnCompleteCallback; private final MotionPauseDetector mMotionPauseDetector; @@ -157,7 +155,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mInputConsumer = inputConsumer; mSwipeSharedState = swipeSharedState; - mDisplayRotation = getSystemService(WindowManager.class).getDefaultDisplay().getRotation(); + mNavBarPosition = new NavBarPosition(base); mDragSlop = QuickStepContract.getQuickStepDragSlopPx(); float slop = QuickStepContract.getQuickStepTouchSlopPx(); mSquaredTouchSlop = slop * slop; @@ -188,9 +186,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC if (mPassedDragSlop && mInteractionHandler != null && !mRecentsViewDispatcher.hasConsumer()) { mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher( - isNavBarOnLeft() - ? ROTATION_SEASCAPE - : (isNavBarOnRight() ? ROTATION_LANDSCAPE : RotationMode.NORMAL))); + mNavBarPosition.getRotationMode())); } int edgeFlags = ev.getEdgeFlags(); ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR); @@ -329,14 +325,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mInteractionHandler.onGestureStarted(); } - private boolean isNavBarOnRight() { - return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90; - } - - private boolean isNavBarOnLeft() { - return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270; - } - private void startTouchTrackingForWindowAnimation(long touchTimeMs) { TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation"); @@ -382,8 +370,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC ViewConfiguration.get(this).getScaledMaximumFlingVelocity()); float velocityX = mVelocityTracker.getXVelocity(mActivePointerId); float velocityY = mVelocityTracker.getYVelocity(mActivePointerId); - float velocity = isNavBarOnRight() ? velocityX - : isNavBarOnLeft() ? -velocityX + float velocity = mNavBarPosition.isRightEdge() ? velocityX + : mNavBarPosition.isLeftEdge() ? -velocityX : velocityY; mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement); @@ -444,9 +432,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } private float getDisplacement(MotionEvent ev) { - if (isNavBarOnRight()) { + if (mNavBarPosition.isRightEdge()) { return ev.getX() - mDownPos.x; - } else if (isNavBarOnLeft()) { + } else if (mNavBarPosition.isLeftEdge()) { return mDownPos.x - ev.getX(); } else { return ev.getY() - mDownPos.y; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java index 5931da0b2c..70ea62796d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java @@ -51,7 +51,7 @@ public class OverviewInputConsumer private final boolean mStartingInActivityBounds; private boolean mTargetHandledTouch; - OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor, + public OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) { mActivity = activity; mInputMonitor = inputMonitor; @@ -115,12 +115,12 @@ public class OverviewInputConsumer } } - public static InputConsumer newInstance(ActivityControlHelper activityHelper, - @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) { + public static InputConsumer newInstanceWithinActivityBounds( + ActivityControlHelper activityHelper) { BaseDraggingActivity activity = activityHelper.getCreatedActivity(); if (activity == null) { return InputConsumer.NO_OP; } - return new OverviewInputConsumer(activity, inputMonitor, startingInActivityBounds); + return new OverviewInputConsumer(activity, null, true); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java new file mode 100644 index 0000000000..425b8b6b0b --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java @@ -0,0 +1,151 @@ +/* + * 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 static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_MOVE; +import static android.view.MotionEvent.ACTION_UP; + +import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; +import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; + +import android.content.Context; +import android.graphics.PointF; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.ViewConfiguration; + +import com.android.launcher3.Utilities; +import com.android.quickstep.OverviewCallbacks; +import com.android.quickstep.util.NavBarPosition; +import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.InputMonitorCompat; + +public class OverviewWithoutFocusInputConsumer implements InputConsumer { + + private final InputMonitorCompat mInputMonitor; + private final boolean mDisableHorizontalSwipe; + private final PointF mDownPos = new PointF(); + private final float mSquaredTouchSlop; + private final Context mContext; + private final NavBarPosition mNavBarPosition; + + private boolean mInterceptedTouch; + private VelocityTracker mVelocityTracker; + + + public OverviewWithoutFocusInputConsumer(Context context, InputMonitorCompat inputMonitor, + boolean disableHorizontalSwipe) { + mInputMonitor = inputMonitor; + mDisableHorizontalSwipe = disableHorizontalSwipe; + mContext = context; + mSquaredTouchSlop = Utilities.squaredTouchSlop(context); + mNavBarPosition = new NavBarPosition(context); + + mVelocityTracker = VelocityTracker.obtain(); + } + + @Override + public int getType() { + return TYPE_OVERVIEW_WITHOUT_FOCUS; + } + + @Override + public boolean allowInterceptByParent() { + return !mInterceptedTouch; + } + + private void endTouchTracking() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + @Override + public void onMotionEvent(MotionEvent ev) { + if (mVelocityTracker == null) { + return; + } + + mVelocityTracker.addMovement(ev); + switch (ev.getActionMasked()) { + case ACTION_DOWN: { + mDownPos.set(ev.getX(), ev.getY()); + break; + } + case ACTION_MOVE: { + if (!mInterceptedTouch) { + float displacementX = ev.getX() - mDownPos.x; + float displacementY = ev.getY() - mDownPos.y; + if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) { + if (mDisableHorizontalSwipe + && Math.abs(displacementX) > Math.abs(displacementY)) { + // Horizontal gesture is not allowed in this region + endTouchTracking(); + break; + } + + mInterceptedTouch = true; + + if (mInputMonitor != null) { + mInputMonitor.pilferPointers(); + } + } + } + break; + } + + case ACTION_CANCEL: + endTouchTracking(); + break; + + case ACTION_UP: { + finishTouchTracking(ev); + endTouchTracking(); + break; + } + } + } + + private void finishTouchTracking(MotionEvent ev) { + mVelocityTracker.computeCurrentVelocity(100); + float velocityX = mVelocityTracker.getXVelocity(); + float velocityY = mVelocityTracker.getYVelocity(); + float velocity = mNavBarPosition.isRightEdge() + ? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY); + + final boolean triggerQuickstep; + if (Math.abs(velocity) >= ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) { + triggerQuickstep = velocity > 0; + } else { + float displacementX = mDisableHorizontalSwipe ? 0 : (ev.getX() - mDownPos.x); + float displacementY = ev.getY() - mDownPos.y; + triggerQuickstep = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop; + } + + if (triggerQuickstep) { + OverviewCallbacks.get(mContext).closeAllWindows(); + ActivityManagerWrapper.getInstance() + .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); + TOUCH_INTERACTION_LOG.addLog("startQuickstep"); + } else { + // ignore + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java new file mode 100644 index 0000000000..3ce341d8cf --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java @@ -0,0 +1,55 @@ +/* + * 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.util; + +import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE; +import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE; +import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; + +import android.content.Context; +import android.view.Surface; +import android.view.WindowManager; + +import com.android.launcher3.graphics.RotationMode; +import com.android.quickstep.SysUINavigationMode; + +/** + * Utility class to check nav bar position + */ +public class NavBarPosition { + + private final SysUINavigationMode.Mode mMode; + private final int mDisplayRotation; + + public NavBarPosition(Context context) { + mMode = SysUINavigationMode.getMode(context); + mDisplayRotation = context.getSystemService(WindowManager.class) + .getDefaultDisplay().getRotation(); + } + + public boolean isRightEdge() { + return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90; + } + + public boolean isLeftEdge() { + return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270; + } + + public RotationMode getRotationMode() { + return isLeftEdge() ? ROTATION_SEASCAPE + : (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL); + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index 837c2dc935..9eda2f9d4d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -28,13 +28,20 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty; +import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager; +import com.android.launcher3.LauncherStateManager.AnimationConfig; import com.android.launcher3.R; import com.android.launcher3.ShortcutAndWidgetContainer; +import com.android.launcher3.anim.AnimatorSetBuilder; +import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.anim.SpringObjectAnimator; import java.util.ArrayList; import java.util.List; +import static com.android.launcher3.LauncherState.BACKGROUND_APP; +import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.anim.Interpolators.LINEAR; /** @@ -56,7 +63,7 @@ public class StaggeredWorkspaceAnim { private final float mSpringTransY; private final View mViewToIgnore; - private final List mAnimators = new ArrayList<>(); + private final List mAnimators = new ArrayList<>(); /** * @param floatingViewOriginalView The FloatingIconView's original view. @@ -104,6 +111,9 @@ public class StaggeredWorkspaceAnim { View qsb = launcher.findViewById(R.id.search_container_all_apps); addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows); } + + addWorkspaceScrimAnimationForState(launcher, BACKGROUND_APP, 0); + addWorkspaceScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS); } /** @@ -150,4 +160,14 @@ public class StaggeredWorkspaceAnim { alpha.setStartDelay(startDelay); mAnimators.add(alpha); } + + private void addWorkspaceScrimAnimationForState(Launcher launcher, LauncherState state, + long duration) { + AnimatorSetBuilder scrimAnimBuilder = new AnimatorSetBuilder(); + AnimationConfig scrimAnimConfig = new AnimationConfig(); + scrimAnimConfig.duration = duration; + PropertySetter scrimPropertySetter = scrimAnimConfig.getPropertySetter(scrimAnimBuilder); + launcher.getWorkspace().getStateTransitionAnimation().setScrim(scrimPropertySetter, state); + mAnimators.add(scrimAnimBuilder.build()); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index deedd21adb..5b2e27e539 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -20,6 +20,7 @@ import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON; +import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; @@ -30,25 +31,20 @@ import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; import android.view.View; -import androidx.annotation.Nullable; - import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager.StateListener; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; -import com.android.launcher3.util.PendingAnimation; -import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode; -import com.android.quickstep.hints.ProactiveHintsContainer; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper.TransformParams; import com.android.quickstep.util.LayoutUtils; @@ -57,11 +53,9 @@ import com.android.quickstep.util.LayoutUtils; * {@link RecentsView} used in Launcher activity */ @TargetApi(Build.VERSION_CODES.O) -public class LauncherRecentsView extends RecentsView { +public class LauncherRecentsView extends RecentsView implements StateListener { private final TransformParams mTransformParams = new TransformParams(); - private final int mChipOverhang; - @Nullable private ProactiveHintsContainer mProactiveHintsContainer; public LauncherRecentsView(Context context) { this(context, null); @@ -74,16 +68,7 @@ public class LauncherRecentsView extends RecentsView { public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setContentAlpha(0); - mChipOverhang = (int) context.getResources().getDimension(R.dimen.chip_hint_overhang); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - View hintContainer = mActivity.findViewById(R.id.hints); - mProactiveHintsContainer = - hintContainer instanceof ProactiveHintsContainer - ? (ProactiveHintsContainer) hintContainer : null; + mActivity.getStateManager().addStateListener(this); } @Override @@ -102,11 +87,6 @@ public class LauncherRecentsView extends RecentsView { } } - @Nullable - public ProactiveHintsContainer getProactiveHintsContainer() { - return mProactiveHintsContainer; - } - @Override public void draw(Canvas canvas) { maybeDrawEmptyMessage(canvas); @@ -160,23 +140,6 @@ public class LauncherRecentsView extends RecentsView { @Override protected void getTaskSize(DeviceProfile dp, Rect outRect) { LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect); - if (mProactiveHintsContainer != null) { - BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) mProactiveHintsContainer.getLayoutParams(); - params.bottomMargin = getHeight() - outRect.bottom - mChipOverhang; - params.width = outRect.width(); - } - } - - @Override - public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) { - PendingAnimation anim = super.createTaskLauncherAnimation(tv, duration); - - if (mProactiveHintsContainer != null) { - anim.anim.play(ObjectAnimator.ofFloat( - mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0)); - } - - return anim; } @Override @@ -194,31 +157,6 @@ public class LauncherRecentsView extends RecentsView { } } - @Override - public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView, - boolean shouldRemoveTask, long duration) { - PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView, - shouldRemoveTask, duration); - - if (mProactiveHintsContainer != null) { - anim.anim.play(ObjectAnimator.ofFloat( - mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0)); - anim.addEndListener(onEndListener -> { - if (!onEndListener.isSuccess) { - mProactiveHintsContainer.setHintVisibility(1); - } - }); - } - - return anim; - } - - public void setHintVisibility(float v) { - if (mProactiveHintsContainer != null) { - mProactiveHintsContainer.setHintVisibility(v); - } - } - @Override protected void onTaskLaunched(boolean success) { if (success) { @@ -286,6 +224,22 @@ public class LauncherRecentsView extends RecentsView { PredictionUiStateManager.INSTANCE.get(getContext()).switchClient(Client.HOME); } + @Override + public void onStateTransitionStart(LauncherState toState) { + setOverviewStateEnabled(toState.overviewUi); + setFreezeViewVisibility(true); + } + + @Override + public void onStateTransitionComplete(LauncherState finalState) { + if (finalState == NORMAL || finalState == SPRING_LOADED) { + // Clean-up logic that occurs when recents is no longer in use/visible. + reset(); + } + setOverlayEnabled(finalState == OVERVIEW); + setFreezeViewVisibility(false); + } + @Override public void setOverviewStateEnabled(boolean enabled) { super.setOverviewStateEnabled(enabled); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 1e1007e686..e38a315f8a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -72,6 +72,9 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ListView; +import androidx.annotation.Nullable; +import androidx.dynamicanimation.animation.SpringForce; + import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; @@ -111,9 +114,6 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import java.util.ArrayList; import java.util.function.Consumer; -import androidx.annotation.Nullable; -import androidx.dynamicanimation.animation.SpringForce; - /** * A list of recent tasks. */ @@ -168,8 +168,6 @@ public abstract class RecentsView extends PagedView impl // The threshold at which we update the SystemUI flags when animating from the task into the app public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f; - private static final float[] sTempFloatArray = new float[3]; - protected final T mActivity; private final float mFastFlingVelocity; private final RecentsModel mModel; @@ -189,6 +187,8 @@ public abstract class RecentsView extends PagedView impl private boolean mDwbToastShown; private boolean mDisallowScrollToClearAll; + private boolean mOverlayEnabled; + private boolean mFreezeViewVisibility; /** * TODO: Call reloadIdNeeded in onTaskStackChanged. @@ -428,11 +428,7 @@ public abstract class RecentsView extends PagedView impl // Clear the task data for the removed child if it was visible if (child != mClearAllButton) { TaskView taskView = (TaskView) child; - Task task = taskView.getTask(); - if (mHasVisibleTaskData.get(task.key.id)) { - mHasVisibleTaskData.delete(task.key.id); - taskView.onTaskListVisibilityChanged(false /* visible */); - } + mHasVisibleTaskData.delete(taskView.getTask().key.id); mTaskViewPool.recycle(taskView); } } @@ -455,7 +451,6 @@ public abstract class RecentsView extends PagedView impl public void setOverviewStateEnabled(boolean enabled) { mOverviewStateEnabled = enabled; updateTaskStackListenerState(); - if (!enabled) mDwbToastShown = false; } public void onDigitalWellbeingToastShown() { @@ -582,6 +577,7 @@ public abstract class RecentsView extends PagedView impl } resetTaskVisuals(); onTaskStackUpdated(); + updateEnabledOverlays(); } public int getTaskViewCount() { @@ -780,6 +776,7 @@ public abstract class RecentsView extends PagedView impl unloadVisibleTaskData(); setCurrentPage(0); + mDwbToastShown = false; } public @Nullable TaskView getRunningTaskView() { @@ -1306,7 +1303,25 @@ public abstract class RecentsView extends PagedView impl mEmptyMessagePaint.setAlpha(alphaInt); mEmptyIcon.setAlpha(alphaInt); - setVisibility(alpha > 0 ? VISIBLE : GONE); + if (alpha > 0) { + setVisibility(VISIBLE); + } else if (!mFreezeViewVisibility) { + setVisibility(GONE); + } + } + + /** + * Freezes the view visibility change. When frozen, the view will not change its visibility + * to gone due to alpha changes. + */ + public void setFreezeViewVisibility(boolean freezeViewVisibility) { + if (mFreezeViewVisibility != freezeViewVisibility) { + mFreezeViewVisibility = freezeViewVisibility; + + if (!mFreezeViewVisibility) { + setVisibility(mContentAlpha > 0 ? VISIBLE : GONE); + } + } } @Override @@ -1545,6 +1560,7 @@ public abstract class RecentsView extends PagedView impl protected void notifyPageSwitchListener(int prevPage) { super.notifyPageSwitchListener(prevPage); loadVisibleTaskData(); + updateEnabledOverlays(); } @Override @@ -1685,4 +1701,19 @@ public abstract class RecentsView extends PagedView impl public ClipAnimationHelper getTempClipAnimationHelper() { return mTempClipAnimationHelper; } + + private void updateEnabledOverlays() { + int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1; + int taskCount = getTaskViewCount(); + for (int i = 0; i < taskCount; i++) { + ((TaskView) getChildAt(i)).setOverlayEnabled(i == overlayEnabledPage); + } + } + + public void setOverlayEnabled(boolean overlayEnabled) { + if (mOverlayEnabled != overlayEnabled) { + mOverlayEnabled = overlayEnabled; + updateEnabledOverlays(); + } + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java index c47e943bee..c1f6b82ec2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java @@ -42,6 +42,7 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.RoundedRectRevealOutlineProvider; import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskSystemShortcut; import com.android.quickstep.TaskUtils; import com.android.quickstep.views.IconView.OnScaleUpdateListener; @@ -196,7 +197,7 @@ public class TaskMenuView extends AbstractFloatingView { final BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext()); final List shortcuts = - taskView.getTaskOverlay().getEnabledShortcuts(taskView); + TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView); final int count = shortcuts.size(); for (int i = 0; i < count; ++i) { final TaskSystemShortcut menuOption = shortcuts.get(i); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index df5831b088..8b8240d0a5 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -98,6 +98,9 @@ public class TaskThumbnailView extends View { private float mDimAlphaMultiplier = 1f; private float mSaturation = 1f; + private boolean mOverlayEnabled; + private boolean mRotated; + public TaskThumbnailView(Context context) { this(context, null); } @@ -192,10 +195,6 @@ public class TaskThumbnailView extends View { return 0; } - public TaskOverlay getTaskOverlay() { - return mOverlay; - } - @Override protected void onDraw(Canvas canvas) { RectF currentDrawnInsets = mFullscreenParams.mCurrentDrawnInsets; @@ -257,6 +256,22 @@ public class TaskThumbnailView extends View { return (TaskView) getParent(); } + public void setOverlayEnabled(boolean overlayEnabled) { + if (mOverlayEnabled != overlayEnabled) { + mOverlayEnabled = overlayEnabled; + updateOverlay(); + } + } + + private void updateOverlay() { + // The overlay doesn't really work when the screenshot is rotated, so don't add it. + if (mOverlayEnabled && !mRotated && mBitmapShader != null && mThumbnailData != null) { + mOverlay.initOverlay(mTask, mThumbnailData, mMatrix); + } else { + mOverlay.reset(); + } + } + private void updateThumbnailPaintFilter() { int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255); ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation); @@ -351,12 +366,8 @@ public class TaskThumbnailView extends View { mPaint.setShader(mBitmapShader); } - if (isRotated) { - // The overlay doesn't really work when the screenshot is rotated, so don't add it. - mOverlay.reset(); - } else { - mOverlay.setTaskInfo(mTask, mThumbnailData, mMatrix); - } + mRotated = isRotated; + updateOverlay(); invalidate(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index f8d454f34e..bf3e91ff68 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -39,7 +39,6 @@ import android.os.Handler; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; -import android.util.Property; import android.view.View; import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; @@ -253,10 +252,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return mIconView; } - public TaskOverlayFactory.TaskOverlay getTaskOverlay() { - return mSnapshotView.getTaskOverlay(); - } - public AnimatorPlaybackController createLaunchAnimationForRunningTask() { final PendingAnimation pendingAnimation = getRecentsView().createTaskLauncherAnimation(this, RECENTS_LAUNCH_DURATION); @@ -488,6 +483,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { // Clear any references to the thumbnail (it will be re-read either from the cache or the // system on next bind) mSnapshotView.setThumbnail(mTask, null); + setOverlayEnabled(false); + onTaskListVisibilityChanged(false); if (mTask != null) { mTask.thumbnail = null; } @@ -608,7 +605,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { final Context context = getContext(); final List shortcuts = - mSnapshotView.getTaskOverlay().getEnabledShortcuts(this); + TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this); final int count = shortcuts.size(); for (int i = 0; i < count; ++i) { final TaskSystemShortcut menuOption = shortcuts.get(i); @@ -647,7 +644,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } final List shortcuts = - mSnapshotView.getTaskOverlay().getEnabledShortcuts(this); + TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this); final int count = shortcuts.size(); for (int i = 0; i < count; ++i) { final TaskSystemShortcut menuOption = shortcuts.get(i); @@ -733,6 +730,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return mShowScreenshot; } + public void setOverlayEnabled(boolean overlayEnabled) { + mSnapshotView.setOverlayEnabled(overlayEnabled); + } + /** * We update and subsequently draw these in {@link #setFullscreenProgress(float)}. */ diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index dcf2e3c155..46161cbc8a 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -108,7 +108,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans // Use a shorter duration for x or y translation to create a curve effect private static final long APP_LAUNCH_CURVED_DURATION = 250; private static final long APP_LAUNCH_ALPHA_DURATION = 50; - private static final long APP_LAUNCH_ALPHA_START_DELAY = 50; + private static final long APP_LAUNCH_ALPHA_START_DELAY = 25; // We scale the durations for the downward app launch animations (minus the scale animation). private static final float APP_LAUNCH_DOWN_DUR_SCALE_FACTOR = 0.8f; diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index 4891746140..97cd38a117 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -47,7 +47,6 @@ import com.android.launcher3.LauncherStateManager; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.QuickstepAppTransitionManagerImpl; import com.android.launcher3.Utilities; -import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.proxy.ProxyActivityStarter; import com.android.launcher3.proxy.StartActivityParams; import com.android.quickstep.OverviewInteractionState; @@ -64,10 +63,14 @@ import java.util.zip.Deflater; public class UiFactory extends RecentsUiFactory { - public static Runnable enableLiveTouchControllerChanges(DragLayer dl) { - NavigationModeChangeListener listener = m -> dl.recreateControllers(); - SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(dl.getContext()); - mode.addModeChangeListener(listener); + public static Runnable enableLiveUIChanges(Launcher launcher) { + NavigationModeChangeListener listener = m -> { + launcher.getDragLayer().recreateControllers(); + launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON); + }; + SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(launcher); + SysUINavigationMode.Mode m = mode.addModeChangeListener(listener); + launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON); return () -> mode.removeModeChangeListener(listener); } diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java index c77726e617..a412b3970f 100644 --- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java +++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java @@ -18,14 +18,17 @@ package com.android.quickstep; import com.android.launcher3.ui.AbstractLauncherUiTest; -import org.junit.Rule; +import org.junit.rules.RuleChain; import org.junit.rules.TestRule; /** * Base class for all instrumentation tests that deal with Quickstep. */ public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest { - @Rule - public TestRule mQuickstepOnOffExecutor = - new NavigationModeSwitchRule(mLauncher); + @Override + protected TestRule getRulesInsideActivityMonitor() { + return RuleChain. + outerRule(new NavigationModeSwitchRule(mLauncher)). + around(super.getRulesInsideActivityMonitor()); + } } diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml index 9cab9c2a5e..cca899bda8 100644 --- a/res/layout/launcher.xml +++ b/res/layout/launcher.xml @@ -48,11 +48,6 @@ layout="@layout/overview_panel" android:visibility="gone" /> - - - - \ No newline at end of file diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index 835fee2d3d..a1033f06ce 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -56,9 +56,9 @@ android:paddingBottom="@dimen/folder_label_padding_bottom" android:paddingTop="@dimen/folder_label_padding_top" android:singleLine="true" - android:textColor="?android:attr/textColorTertiary" + android:textColor="?attr/folderTextColor" android:textColorHighlight="?android:attr/colorControlHighlight" - android:textColorHint="?android:attr/textColorHint" + android:textColorHint="?attr/folderTextColor" android:textSize="@dimen/folder_label_text_size" /> 12sp 14sp - - 26dp - 194dp - 15dp - 8dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c1f898c5d0..883e8c642b 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -99,10 +99,6 @@ public class DeviceProfile { public int folderChildTextSizePx; public int folderChildDrawablePaddingPx; - // Hints - public int chipHintHeightPx; - public int chipHintBottomMarginPx; - // Hotseat public int hotseatCellHeightPx; // In portrait: size = height, in landscape: size = width @@ -200,9 +196,6 @@ public class DeviceProfile { workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x); - chipHintHeightPx = res.getDimensionPixelSize(R.dimen.chip_hint_height); - chipHintBottomMarginPx = res.getDimensionPixelSize(R.dimen.chip_hint_bottom_margin); - hotseatBarTopPaddingPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding); hotseatBarBottomPaddingPx = (isTallDevice ? 0 diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 855535b0f3..57a9b161f9 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -879,6 +879,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onStart() { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "Launcher.onStart"); + } RaceConditionTracker.onEvent(ON_START_EVT, ENTER); super.onStart(); if (mLauncherCallbacks != null) { @@ -1063,7 +1066,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, // Setup the drag layer mDragLayer.setup(mDragController, mWorkspace); - mCancelTouchController = UiFactory.enableLiveTouchControllerChanges(mDragLayer); + mCancelTouchController = UiFactory.enableLiveUIChanges(this); mWorkspace.setup(mDragController); // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 3a92dfb961..c63f976a87 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -258,9 +258,6 @@ public class LauncherState { * Called when the start transition ends and the user settles on this particular state. */ public void onStateTransitionEnd(Launcher launcher) { - if (this == NORMAL || this == SPRING_LOADED) { - UiFactory.resetOverview(launcher); - } if (this == NORMAL) { // Clear any rotation locks when going to normal state launcher.getRotationHelper().setCurrentStateRequest(REQUEST_NONE); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index f784226a51..9f846bbc4d 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1394,6 +1394,10 @@ public class Workspace extends PagedView builder.play(stepAnimator); } + public WorkspaceStateTransitionAnimation getStateTransitionAnimation() { + return mStateTransitionAnimation; + } + public void updateAccessibilityFlags() { // TODO: Update the accessibility flags appropriately when dragging. int accessibilityFlag = mLauncher.getStateManager().getState().workspaceAccessibilityFlag; diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 8d0259d050..065d065682 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -130,7 +130,10 @@ public class WorkspaceStateTransitionAnimation { propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y, hotseatScaleAndTranslation.translationY, translationInterpolator); - // Set scrim + setScrim(propertySetter, state); + } + + public void setScrim(PropertySetter propertySetter, LauncherState state) { WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim(); propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher), LINEAR); diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index 9d3c8f75dc..72a1abb833 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -27,6 +27,7 @@ import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; +import android.util.Log; import android.view.DragEvent; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; @@ -491,6 +492,16 @@ public class DragController implements DragDriver.EventListener, TouchController mLastTouch[0] = x; mLastTouch[1] = y; + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TAG, + "handleMoveEvent Conditions " + + mIsInPreDrag + ", " + + (mIsInPreDrag && mOptions.preDragCondition != null) + ", " + + (mIsInPreDrag && mOptions.preDragCondition != null + && mOptions.preDragCondition.shouldStartDrag( + mDistanceSinceScroll))); + } + if (mIsInPreDrag && mOptions.preDragCondition != null && mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) { if (TestProtocol.sDebugTracing) { diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java index cd96d6ed84..abf90e22c8 100644 --- a/src/com/android/launcher3/states/RotationHelper.java +++ b/src/com/android/launcher3/states/RotationHelper.java @@ -73,7 +73,8 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { // This is used to defer setting rotation flags until the activity is being created private boolean mInitialized; - public boolean mDestroyed; + private boolean mDestroyed; + private boolean mRotationHasDifferentUI; private int mLastActivityFlags = -1; @@ -92,8 +93,12 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { } } + public void setRotationHadDifferentUI(boolean rotationHasDifferentUI) { + mRotationHasDifferentUI = rotationHasDifferentUI; + } + public boolean homeScreenCanRotate() { - return mIgnoreAutoRotateSettings || mAutoRotateEnabled + return mRotationHasDifferentUI || mIgnoreAutoRotateSettings || mAutoRotateEnabled || mStateHandlerRequest != REQUEST_NONE || mLauncher.getDeviceProfile().isMultiWindowMode; } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 99efb22cf1..02e6bbdd79 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -72,4 +72,5 @@ public final class TestProtocol { public static final String NO_DRAG_TAG = "b/133009122"; public static final String NO_START_TAG = "b/132900132"; public static final String NO_START_TASK_TAG = "b/133765434"; + public static final String NO_OVERVIEW_EVENT_TAG = "b/134532571"; } diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java index 4fea2e92ae..c24bb67813 100644 --- a/src/com/android/launcher3/util/TraceHelper.java +++ b/src/com/android/launcher3/util/TraceHelper.java @@ -27,16 +27,17 @@ import android.util.MutableLong; import com.android.launcher3.config.FeatureFlags; /** - * A wrapper around {@link Trace} to allow easier proguarding for production builds. + * A wrapper around {@link Trace} with some utility information. * * To enable any tracing log, execute the following command: + * $ adb shell setprop log.tag.LAUNCHER_TRACE VERBOSE * $ adb shell setprop log.tag.TAGNAME VERBOSE */ public class TraceHelper { - private static final boolean ENABLED = FeatureFlags.IS_DOGFOOD_BUILD; + private static final boolean ENABLED = isLoggable("LAUNCHER_TRACE", VERBOSE); - private static final boolean SYSTEM_TRACE = false; + private static final boolean SYSTEM_TRACE = ENABLED; private static final ArrayMap sUpTimes = ENABLED ? new ArrayMap<>() : null; public static void beginSection(String sectionName) { diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 95c96817a0..339681cd69 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -124,6 +124,7 @@ public class FloatingIconView extends View implements private boolean mIsVerticalBarLayout = false; private boolean mIsAdaptiveIcon = false; + private boolean mIsOpening; private @Nullable Drawable mBadge; private @Nullable Drawable mForeground; @@ -178,8 +179,10 @@ public class FloatingIconView extends View implements @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - getViewTreeObserver().addOnGlobalLayoutListener(this); - mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK); + if (!mIsOpening) { + getViewTreeObserver().addOnGlobalLayoutListener(this); + mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK); + } } @Override @@ -326,7 +329,7 @@ public class FloatingIconView extends View implements * - For BubbleTextView, we return the icon bounds. */ private float getLocationBoundsForView(View v, RectF outRect) { - boolean ignoreTransform = true; + boolean ignoreTransform = !mIsOpening; if (v instanceof DeepShortcutView) { v = ((DeepShortcutView) v).getBubbleText(); ignoreTransform = false; @@ -627,6 +630,7 @@ public class FloatingIconView extends View implements view.recycle(); view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout(); + view.mIsOpening = isOpening; view.mOriginalIcon = originalView; view.mPositionOut = positionOut; diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java index 550327d961..e41916cf47 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java @@ -27,7 +27,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState.ScaleAndTranslation; import com.android.launcher3.LauncherStateManager.StateHandler; -import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.util.TouchController; @@ -40,7 +39,7 @@ public class UiFactory { launcher.getDragController(), new AllAppsSwipeController(launcher)}; } - public static Runnable enableLiveTouchControllerChanges(DragLayer dl) { + public static Runnable enableLiveUIChanges(Launcher l) { return null; } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index c7c36b0d40..64fe2d7d79 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -58,19 +58,17 @@ import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.FailureWatcher; import com.android.launcher3.util.rule.LauncherActivityRule; import com.android.launcher3.util.rule.ShellCommandRule; import org.junit.After; import org.junit.Before; import org.junit.Rule; +import org.junit.rules.RuleChain; import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; import org.junit.runners.model.Statement; -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -93,11 +91,11 @@ public abstract class AbstractLauncherUiTest { public static final long SHORT_UI_TIMEOUT = 300; public static final long DEFAULT_UI_TIMEOUT = 10000; private static final String TAG = "AbstractLauncherUiTest"; - private static int sScreenshotCount = 0; protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation()); - protected final LauncherInstrumentation mLauncher; + protected final LauncherInstrumentation mLauncher = + new LauncherInstrumentation(getInstrumentation()); protected Context mTargetContext; protected String mTargetPackage; @@ -108,11 +106,9 @@ public abstract class AbstractLauncherUiTest { throw new RuntimeException(e); } if (TestHelpers.isInLauncherProcess()) Utilities.enableRunningInTestHarnessForTests(); - mLauncher = new LauncherInstrumentation(getInstrumentation()); } - @Rule - public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + protected final LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); @Rule public ShellCommandRule mDefaultLauncherRule = @@ -166,43 +162,18 @@ public abstract class AbstractLauncherUiTest { } } : base; + protected TestRule getRulesInsideActivityMonitor() { + return new FailureWatcher(this); + } + @Rule - public TestWatcher mFailureWatcher = new TestWatcher() { - private void dumpViewHierarchy() { - final ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - mDevice.dumpWindowHierarchy(stream); - stream.flush(); - stream.close(); - for (String line : stream.toString().split("\\r?\\n")) { - Log.e(TAG, line.trim()); - } - } catch (IOException e) { - Log.e(TAG, "error dumping XML to logcat", e); - } - } + public TestRule mOrderSensitiveRules = RuleChain. + outerRule(mActivityMonitor). + around(getRulesInsideActivityMonitor()); - @Override - protected void failed(Throwable e, Description description) { - if (mDevice == null) return; - final String pathname = getInstrumentation().getTargetContext(). - getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png"; - Log.e(TAG, "Failed test " + description.getMethodName() + - ", screenshot will be saved to " + pathname + - ", track trace is below, UI object dump is further below:\n" + - Log.getStackTraceString(e)); - dumpViewHierarchy(); - - try { - final String dumpsysResult = mDevice.executeShellCommand( - "dumpsys activity service TouchInteractionService"); - Log.d(TAG, "TouchInteractionService: " + dumpsysResult); - } catch (IOException ex) { - } - - mDevice.takeScreenshot(new File(pathname)); - } - }; + public UiDevice getDevice() { + return mDevice; + } @Before public void setUp() throws Exception { diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java new file mode 100644 index 0000000000..09cc98de08 --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java @@ -0,0 +1,59 @@ +package com.android.launcher3.util.rule; + +import static androidx.test.InstrumentationRegistry.getInstrumentation; + +import android.util.Log; + +import com.android.launcher3.ui.AbstractLauncherUiTest; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; + +public class FailureWatcher extends TestWatcher { + private static final String TAG = "FailureWatcher"; + private static int sScreenshotCount = 0; + private AbstractLauncherUiTest mAbstractLauncherUiTest; + + public FailureWatcher(AbstractLauncherUiTest abstractLauncherUiTest) { + mAbstractLauncherUiTest = abstractLauncherUiTest; + } + + private void dumpViewHierarchy() { + final ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + mAbstractLauncherUiTest.getDevice().dumpWindowHierarchy(stream); + stream.flush(); + stream.close(); + for (String line : stream.toString().split("\\r?\\n")) { + Log.e(TAG, line.trim()); + } + } catch (IOException e) { + Log.e(TAG, "error dumping XML to logcat", e); + } + } + + @Override + protected void failed(Throwable e, Description description) { + if (mAbstractLauncherUiTest.getDevice() == null) return; + final String pathname = getInstrumentation().getTargetContext(). + getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png"; + Log.e(TAG, "Failed test " + description.getMethodName() + + ", screenshot will be saved to " + pathname + + ", track trace is below, UI object dump is further below:\n" + + Log.getStackTraceString(e)); + dumpViewHierarchy(); + + try { + final String dumpsysResult = mAbstractLauncherUiTest.getDevice().executeShellCommand( + "dumpsys activity service TouchInteractionService"); + Log.d(TAG, "TouchInteractionService: " + dumpsysResult); + } catch (IOException ex) { + } + + mAbstractLauncherUiTest.getDevice().takeScreenshot(new File(pathname)); + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index ce952983f9..6c46192356 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -59,6 +59,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { } protected void goToOverviewUnchecked(int expectedState) { + mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING); switch (mLauncher.getNavigationModel()) { case ZERO_BUTTON: { final int centerX = mLauncher.getDevice().getDisplayWidth() / 2; @@ -103,6 +104,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { mLauncher.waitForSystemUiObject("recent_apps").click(); break; } + mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING); } protected String getSwipeHeightRequestName() {