diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2019-06-13 08:34:48 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2019-06-13 15:36:46 +0000 |
commit | 0e57817adce06277b7ae07fdc5c0d1c4e1723958 (patch) | |
tree | 55dec84a639d2e1a979301523a9f3aded6e6debc /quickstep/recents_ui_overrides | |
parent | 0ea61abe1012fa25e9b15e95e04b368471c4ac6a (diff) | |
parent | 3d6e96d5265cdea78ad4e01b0f9fde0eea539094 (diff) | |
download | android_packages_apps_Trebuchet-0e57817adce06277b7ae07fdc5c0d1c4e1723958.tar.gz android_packages_apps_Trebuchet-0e57817adce06277b7ae07fdc5c0d1c4e1723958.tar.bz2 android_packages_apps_Trebuchet-0e57817adce06277b7ae07fdc5c0d1c4e1723958.zip |
Merging ub-launcher3-qt-dev, build 5656472
Test: Manual
Bug:125844074 P2 Final UX and animations for Launcher DWB integration
Bug:129985827 P1 [Fully Gestural Navigation] Delay Recents animation when swiping up
Bug:131360075 P1 [Gesture Nav] Polish/finish landscape
Bug:132900132 P1 Apparently, tests start running while provisioning is still in progress
Bug:133009122 P2 Rare flake: dragged launchable to workspace, but the current state is not WORKSPACE; Can't find a launcher object; selector: BySelector [RES='\Qcom.google.android.apps.nexuslauncher:id/apps_view\E']
Bug:133443741 P2 Provide a ImageApi.cropBitmap API between Launcher/UI library
Bug:133765434 P1 [Flaky test] Launching task didn't open a new window
Bug:133867119 P2 Lab-only flake: want to switch from workspace to all apps; Swipe failed to receive an event for the swipe end
Bug:134091263 P1 Can't swipe up
Bug:134164918 P1 STOPSHIP: Disable chips hard-coded value in qt_dev Launcher
Bug:134309036 P1 Immediately dragging up after opening recents causes a flicker with fully gestural navigation enabled
Bug:134309189 P1 Immediately dragging up from recents doesn't open all apps with fully gestural navigation enabled
Bug:134406364 P2 [Multiuser] Pixel launcher crashed after switching to secondary user.
Bug:134559760 P2 Launcher crashed when keeping phone in face enroll page for 2~3 minutes. (fail rate: 3 of 10 trials)
Bug:134707989 P1 List widgets are reinitialized on rotation
Bug:134725160 P2 Swiping up on two-button nav does not hide icons with 3p launcher
Bug:134919468 P2 [Q-Preview4] Quickstep crash on app remaining time tap on Essential phone
Bug:134963243 P4 In multiwindow mode, seeing a shade on scrolling all apps screen.
Bug:134964922 P1 Wrap createLegacyIconExtras in a target sdk check
Bug:134969824 P4 Pixel launcher crashed while resuming chrome video in PIP mode
Bug:134971634 P1 onSystemUiStateChanged and some other binder calls can crash Launcher
Bug:135008910 P1 Launcher with black status bar/nav bar icons
Bug:135038270 P1 Apps getting stuck while switching in the overiew screen.
Bug:135050372 P1 Regression: Can no longer double swipe nav bar from an app to go to all apps in 2-button mode
Bug:135114549 P1 TaskView becomes visible at the end to swipe-down
Bug:issue priority summary
Change-Id: Ief4ecb36f17e168cdeb7aef930bcb051e29dbc02
Diffstat (limited to 'quickstep/recents_ui_overrides')
18 files changed, 341 insertions, 140 deletions
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 f1d6450a5..1c6696858 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 @@ -64,10 +64,12 @@ public class BackgroundAppState extends OverviewState { public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) { // Initialize the recents view scale to what it would be when starting swipe up RecentsView recentsView = launcher.getOverviewPanel(); - if (recentsView.getTaskViewCount() == 0) { + int taskCount = recentsView.getTaskViewCount(); + if (taskCount == 0) { return super.getOverviewScaleAndTranslation(launcher); } - TaskView dummyTask = recentsView.getTaskViewAt(recentsView.getCurrentPage()); + TaskView dummyTask = recentsView.getTaskViewAt(Math.max(taskCount - 1, + recentsView.getCurrentPage())); return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask) .getScaleAndTranslation(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java index ed511f5f2..cdc271fdd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.uioverrides.states; +import android.os.Handler; +import android.os.Looper; + import com.android.launcher3.Launcher; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.views.RecentsView; @@ -27,6 +30,8 @@ import com.android.quickstep.views.TaskView; */ public class QuickSwitchState extends BackgroundAppState { + private static final String TAG = "QuickSwitchState"; + public QuickSwitchState(int id) { super(id, LauncherLogProto.ContainerType.APP); } @@ -48,7 +53,12 @@ public class QuickSwitchState extends BackgroundAppState { public void onStateTransitionEnd(Launcher launcher) { TaskView tasktolaunch = launcher.<RecentsView>getOverviewPanel().getTaskViewAt(0); if (tasktolaunch != null) { - tasktolaunch.launchTask(false); + tasktolaunch.launchTask(false, success -> { + if (!success) { + launcher.getStateManager().goToState(OVERVIEW); + tasktolaunch.notifyTaskLaunchFailed(TAG); + } + }, new Handler(Looper.getMainLooper())); } else { launcher.getStateManager().goToState(NORMAL); } 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 2c42fd63a..4ae6d87b8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -224,4 +224,10 @@ public final class FallbackActivityControllerHelper implements public boolean isInLiveTileMode() { return false; } + + @Override + public void onLaunchTaskFailed(RecentsActivity activity) { + // TODO: probably go back to overview instead. + activity.<RecentsView>getOverviewPanel().startHome(); + } } 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 1b82bcb57..0d06c19ab 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -16,13 +16,17 @@ package com.android.quickstep; import static android.view.View.TRANSLATION_Y; + import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.LauncherStateManager.ANIM_ALL; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS; +import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; +import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.WindowTransformSwipeHandler.RECENTS_ATTACH_DURATION; @@ -44,16 +48,19 @@ import android.view.animation.Interpolator; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; +import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.dynamicanimation.animation.SpringForce; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherInitListenerEx; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.AnimatorSetBuilder; 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; @@ -100,6 +107,13 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe } @Override + public void onSwipeUpToHomeComplete(Launcher activity) { + // Ensure recents is at the correct position for NORMAL state. For example, when we detach + // recents, we assume the first task is invisible, making translation off by one task. + activity.getStateManager().reapplyState(); + } + + @Override public void onAssistantVisibilityChanged(float visibility) { Launcher launcher = getCreatedActivity(); if (launcher != null) { @@ -156,18 +170,23 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe public AnimatorPlaybackController createActivityAnimationToHome() { // Return an empty APC here since we have an non-user controlled animation to home. long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); - AnimatorSet as = new AnimatorSet(); - as.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - activity.getStateManager().goToState(NORMAL, false); - } - }); - return AnimatorPlaybackController.wrap(as, accuracy); + return activity.getStateManager().createAnimationToNewWorkspace(NORMAL, accuracy, + 0 /* animComponents */); } @Override public void playAtomicAnimation(float velocity) { + // Setup workspace with 0 duration to prepare for our staggered animation. + LauncherStateManager stateManager = activity.getStateManager(); + AnimatorSetBuilder builder = new AnimatorSetBuilder(); + // setRecentsAttachedToAppWindow() will animate recents out. + builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW); + stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0); + builder.build().start(); + + // Stop scrolling so that it doesn't interfere with the translation offscreen. + recentsView.getScroller().forceFinished(true); + new StaggeredWorkspaceAnim(activity, workspaceView, velocity).start(); } }; @@ -196,12 +215,11 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe // Optimization, hide the all apps view to prevent layout while initializing activity.getAppsView().getContentView().setVisibility(View.GONE); - AccessibilityManagerCompat.sendStateEventToTest(activity, fromState.ordinal); - return new AnimationFactory() { private Animator mShelfAnim; private ShelfAnimState mShelfState; - private Animator mAttachToWindowAnim; + private Animator mAttachToWindowFadeAnim; + private SpringAnimation mAttachToWindowTranslationXAnim; private boolean mIsAttachedToWindow; @Override @@ -267,20 +285,60 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe return; } mIsAttachedToWindow = attached; - if (mAttachToWindowAnim != null) { - mAttachToWindowAnim.cancel(); + if (mAttachToWindowFadeAnim != null) { + mAttachToWindowFadeAnim.cancel(); } - mAttachToWindowAnim = ObjectAnimator.ofFloat(activity.getOverviewPanel(), + RecentsView recentsView = activity.getOverviewPanel(); + mAttachToWindowFadeAnim = ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, attached ? 1 : 0); - mAttachToWindowAnim.addListener(new AnimatorListenerAdapter() { + + int runningTaskIndex = recentsView.getRunningTaskIndex(); + if (runningTaskIndex == 0) { + // If we are on the first task (we haven't quick switched), translate recents in + // from the side. Calculate the start translation based on current scale/scroll. + float currScale = recentsView.getScaleX(); + float scrollOffsetX = recentsView.getScrollOffset(); + + float offscreenX = NORMAL.getOverviewScaleAndTranslation(activity).translationX; + // The first task is hidden, so offset by its width. + int firstTaskWidth = recentsView.getTaskViewAt(0).getWidth(); + offscreenX -= (firstTaskWidth + recentsView.getPageSpacing()) * currScale; + // Offset since scale pushes tasks outwards. + offscreenX += firstTaskWidth * (currScale - 1) / 2; + offscreenX = Math.max(0, offscreenX); + if (recentsView.isRtl()) { + offscreenX = -offscreenX; + } + + float fromTranslationX = attached ? offscreenX - scrollOffsetX : 0; + float toTranslationX = attached ? 0 : offscreenX - scrollOffsetX; + if (mAttachToWindowTranslationXAnim == null) { + mAttachToWindowTranslationXAnim = new SpringAnimation(recentsView, + SpringAnimation.TRANSLATION_X).setSpring(new SpringForce() + .setDampingRatio(0.8f) + .setStiffness(250)); + } + if (!recentsView.isShown() && animate) { + recentsView.setTranslationX(fromTranslationX); + mAttachToWindowTranslationXAnim.setStartValue(fromTranslationX); + } + mAttachToWindowTranslationXAnim.animateToFinalPosition(toTranslationX); + if (!animate && mAttachToWindowTranslationXAnim.canSkipToEnd()) { + mAttachToWindowTranslationXAnim.skipToEnd(); + } + + mAttachToWindowFadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2); + } else { + mAttachToWindowFadeAnim.setInterpolator(ACCEL_DEACCEL); + } + mAttachToWindowFadeAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mAttachToWindowAnim = null; + mAttachToWindowFadeAnim = null; } }); - mAttachToWindowAnim.setInterpolator(ACCEL_DEACCEL); - mAttachToWindowAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0); - mAttachToWindowAnim.start(); + mAttachToWindowFadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0); + mAttachToWindowFadeAnim.start(); } }; } @@ -448,4 +506,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe return launcher != null && launcher.getStateManager().getState() == OVERVIEW && launcher.isStarted(); } + + @Override + public void onLaunchTaskFailed(Launcher launcher) { + launcher.getStateManager().goToState(OVERVIEW); + } }
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java index 5a039cd90..6689ce3d7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java @@ -15,8 +15,11 @@ */ package com.android.quickstep; +import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; + import android.util.Log; +import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.RecentsAnimationListenerSet; @@ -29,7 +32,7 @@ import java.io.PrintWriter; */ public class SwipeSharedState implements SwipeAnimationListener { - private final OverviewComponentObserver mOverviewComponentObserver; + private OverviewComponentObserver mOverviewComponentObserver; private RecentsAnimationListenerSet mRecentsAnimationListener; private SwipeAnimationTargetSet mLastAnimationTarget; @@ -42,8 +45,8 @@ public class SwipeSharedState implements SwipeAnimationListener { public boolean recentsAnimationFinishInterrupted; public int nextRunningTaskId = -1; - public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) { - mOverviewComponentObserver = overviewComponentObserver; + public void setOverviewComponentObserver(OverviewComponentObserver observer) { + mOverviewComponentObserver = observer; } @Override @@ -72,6 +75,12 @@ public class SwipeSharedState implements SwipeAnimationListener { private void clearListenerState() { if (mRecentsAnimationListener != null) { mRecentsAnimationListener.removeListener(this); + mRecentsAnimationListener.cancelListener(); + if (mLastAnimationRunning && mLastAnimationTarget != null) { + Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), + mLastAnimationTarget::cancelAnimation); + mLastAnimationTarget = null; + } } mRecentsAnimationListener = null; clearAnimationTarget(); @@ -98,9 +107,10 @@ public class SwipeSharedState implements SwipeAnimationListener { } clearListenerState(); - mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver - .getActivityControlHelper().shouldMinimizeSplitScreen(), - this::onSwipeAnimationFinished); + boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false + : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen(); + mRecentsAnimationListener = new RecentsAnimationListenerSet( + shouldMinimiseSplitScreen, this::onSwipeAnimationFinished); mRecentsAnimationListener.addListener(this); return mRecentsAnimationListener; } 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 5104fb880..b90f6c2b1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -24,6 +24,7 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.ResourceBasedOverride; +import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -62,7 +63,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { return shortcuts; } - public TaskOverlay createOverlay(View thumbnailView) { + public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) { return new TaskOverlay(); } 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 dc354404a..097ff4659 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -17,7 +17,12 @@ package com.android.quickstep; import static android.view.MotionEvent.ACTION_DOWN; +import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM; +import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; +import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI; +import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; @@ -27,7 +32,6 @@ 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; @@ -61,6 +65,7 @@ import android.view.Surface; import android.view.WindowManager; import androidx.annotation.BinderThread; +import androidx.annotation.UiThread; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; @@ -81,6 +86,7 @@ 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.ResetGestureInputConsumer; import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -94,7 +100,6 @@ import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -146,10 +151,7 @@ public class TouchInteractionService extends Service implements mISystemUiProxy = ISystemUiProxy.Stub .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY)); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor); - runWhenUserUnlocked(() -> { - mRecentsModel.setSystemUiProxy(mISystemUiProxy); - mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); - }); + MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet); } @Override @@ -182,16 +184,9 @@ public class TouchInteractionService extends Service implements @Override public void onAssistantVisibilityChanged(float visibility) { - if (mOverviewComponentObserver == null) { - // Save the visibility to be applied when the user is unlocked - mPendingAssistantVisibility = visibility; - return; - } - - MAIN_THREAD_EXECUTOR.execute(() -> { - mOverviewComponentObserver.getActivityControlHelper() - .onAssistantVisibilityChanged(visibility); - }); + mLastAssistantVisibility = visibility; + MAIN_THREAD_EXECUTOR.execute( + TouchInteractionService.this::onAssistantVisibilityChanged); } public void onBackAction(boolean completed, int downX, int downY, boolean isButton, @@ -208,8 +203,7 @@ public class TouchInteractionService extends Service implements public void onSystemUiStateChanged(int stateFlags) { mSystemUiStateFlags = stateFlags; - mOverviewInteractionState.setSystemUiStateFlags(stateFlags); - mOverviewComponentObserver.onSystemUiStateChanged(stateFlags); + MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged); } /** Deprecated methods **/ @@ -236,6 +230,10 @@ public class TouchInteractionService extends Service implements return sConnected; } + private final SwipeSharedState mSwipeSharedState = new SwipeSharedState(); + private final InputConsumer mResetGestureInputConsumer = + new ResetGestureInputConsumer(mSwipeSharedState); + private KeyguardManager mKM; private ActivityManagerWrapper mAM; private RecentsModel mRecentsModel; @@ -246,13 +244,11 @@ public class TouchInteractionService extends Service implements private OverviewCallbacks mOverviewCallbacks; private TaskOverlayFactory mTaskOverlayFactory; private InputConsumerController mInputConsumer; - private SwipeSharedState mSwipeSharedState; private boolean mAssistantAvailable; - private float mPendingAssistantVisibility = 0; + private float mLastAssistantVisibility = 0; private @SystemUiStateFlags int mSystemUiStateFlags; private boolean mIsUserUnlocked; - private List<Runnable> mOnUserUnlockedCallbacks; private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -286,7 +282,7 @@ public class TouchInteractionService extends Service implements // Everything else should be initialized in initWhenUserUnlocked() below. mKM = getSystemService(KeyguardManager.class); mMainChoreographer = Choreographer.getInstance(); - mOnUserUnlockedCallbacks = new ArrayList<>(); + mAM = ActivityManagerWrapper.getInstance(); if (UserManagerCompat.getInstance(this).isUserUnlocked(Process.myUserHandle())) { initWhenUserUnlocked(); @@ -413,26 +409,21 @@ public class TouchInteractionService extends Service implements } private void initWhenUserUnlocked() { - mIsUserUnlocked = true; - - mAM = ActivityManagerWrapper.getInstance(); mRecentsModel = RecentsModel.INSTANCE.get(this); mOverviewComponentObserver = new OverviewComponentObserver(this); - mOverviewComponentObserver.getActivityControlHelper().onAssistantVisibilityChanged( - mPendingAssistantVisibility); mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver); mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this); mOverviewCallbacks = OverviewCallbacks.get(this); mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this); - mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); - mInputConsumer.registerInputConsumer(); + mIsUserUnlocked = true; - for (Runnable callback : mOnUserUnlockedCallbacks) { - callback.run(); - } - mOnUserUnlockedCallbacks.clear(); + mSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver); + mInputConsumer.registerInputConsumer(); + onSystemUiProxySet(); + onSystemUiFlagsChanged(); + onAssistantVisibilityChanged(); // Temporarily disable model preload // new ModelPreload().start(this); @@ -440,11 +431,27 @@ public class TouchInteractionService extends Service implements Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver); } - private void runWhenUserUnlocked(Runnable callback) { + @UiThread + private void onSystemUiProxySet() { if (mIsUserUnlocked) { - callback.run(); - } else { - mOnUserUnlockedCallbacks.add(callback); + mRecentsModel.setSystemUiProxy(mISystemUiProxy); + mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + } + } + + @UiThread + private void onSystemUiFlagsChanged() { + if (mIsUserUnlocked) { + mOverviewInteractionState.setSystemUiStateFlags(mSystemUiStateFlags); + mOverviewComponentObserver.onSystemUiStateChanged(mSystemUiStateFlags); + } + } + + @UiThread + private void onAssistantVisibilityChanged() { + if (mIsUserUnlocked) { + mOverviewComponentObserver.getActivityControlHelper().onAssistantVisibilityChanged( + mLastAssistantVisibility); } } @@ -510,12 +517,14 @@ public class TouchInteractionService extends Service implements // launched while device is locked even after exiting direct boot mode (e.g. camera). return createDeviceLockedInputConsumer(mAM.getRunningTask(0)); } else { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } } - InputConsumer base = isInValidSystemUiState - ? newBaseConsumer(useSharedState, event) : InputConsumer.NO_OP; + // When using sharedState, bypass systemState check as this is a followup gesture and the + // first gesture started in a valid system state. + InputConsumer base = isInValidSystemUiState || useSharedState + ? newBaseConsumer(useSharedState, event) : mResetGestureInputConsumer; if (mMode == Mode.NO_BUTTON) { final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); @@ -560,7 +569,7 @@ public class TouchInteractionService extends Service implements if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher && !mSwipeSharedState.recentsAnimationFinishInterrupted) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } else if (mSwipeSharedState.recentsAnimationFinishInterrupted) { // If the finish animation was interrupted, then continue using the other activity input // consumer but with the next task as the running task @@ -573,7 +582,7 @@ public class TouchInteractionService extends Service implements return createOverviewInputConsumer(event); } else if (mGestureBlockingActivity != null && runningTaskInfo != null && mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } else { return createOtherActivityInputConsumer(event, runningTaskInfo); } @@ -604,7 +613,7 @@ public class TouchInteractionService extends Service implements return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, taskInfo.taskId); } else { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } } @@ -613,10 +622,10 @@ public class TouchInteractionService extends Service implements mOverviewComponentObserver.getActivityControlHelper(); BaseDraggingActivity activity = activityControl.getCreatedActivity(); if (activity == null) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } - if (activity.getRootView().hasWindowFocus()) { + if (activity.getRootView().hasWindowFocus() || mSwipeSharedState.goingToLauncher) { return new OverviewInputConsumer(activity, mInputMonitorCompat, false /* startingInActivityBounds */); } else { @@ -630,7 +639,8 @@ public class TouchInteractionService extends Service implements */ private void onConsumerInactive(InputConsumer caller) { if (mConsumer == caller) { - mConsumer = InputConsumer.NO_OP; + mConsumer = mResetGestureInputConsumer; + mUncheckedConsumer = mConsumer; } } @@ -666,6 +676,13 @@ public class TouchInteractionService extends Service implements mSwipeSharedState.dump(" ", pw); } pw.println(" mConsumer=" + mConsumer.getName()); + pw.println("FeatureFlags:"); + pw.println(" APPLY_CONFIG_AT_RUNTIME=" + APPLY_CONFIG_AT_RUNTIME.get()); + pw.println(" QUICKSTEP_SPRINGS=" + QUICKSTEP_SPRINGS.get()); + pw.println(" ADAPTIVE_ICON_WINDOW_ANIM=" + ADAPTIVE_ICON_WINDOW_ANIM.get()); + pw.println(" ENABLE_QUICKSTEP_LIVE_TILE=" + ENABLE_QUICKSTEP_LIVE_TILE.get()); + pw.println(" ENABLE_HINTS_IN_OVERVIEW=" + ENABLE_HINTS_IN_OVERVIEW.get()); + pw.println(" FAKE_LANDSCAPE_UI=" + FAKE_LANDSCAPE_UI.get()); TOUCH_INTERACTION_LOG.dump("", pw); } 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 c7841d98e..e9aa6d078 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -21,7 +21,6 @@ import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; -import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; @@ -218,7 +217,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW)); private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured"; - private static final long SHELF_ANIM_DURATION = 120; + private static final long SHELF_ANIM_DURATION = 240; public static final long RECENTS_ATTACH_DURATION = 300; // Start resisting when swiping past this factor of mTransitionDragLength. @@ -602,7 +601,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> } public void onMotionPauseChanged(boolean isPaused) { - setShelfState(isPaused ? PEEK : HIDE, FAST_OUT_SLOW_IN, SHELF_ANIM_DURATION); + setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION); } public void maybeUpdateRecentsAttachedState() { @@ -625,7 +624,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> : mRecentsAnimationWrapper.targetSet.findTask(mRunningTaskId); final boolean recentsAttachedToAppWindow; int runningTaskIndex = mRecentsView.getRunningTaskIndex(); - if (mContinuingLastGesture) { + if (mGestureEndTarget != null) { + recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow; + } else if (mContinuingLastGesture + && mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) { recentsAttachedToAppWindow = true; animate = false; } else if (runningTaskTarget != null && isNotInRecents(runningTaskTarget)) { @@ -633,17 +635,16 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> recentsAttachedToAppWindow = true; animate = false; } else { - if (mGestureEndTarget != null) { - recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow; - } else { - recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask; - } + recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask; if (animate) { // Only animate if an adjacent task view is visible on screen. TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1); TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1); + float prevTranslationX = mRecentsView.getTranslationX(); + mRecentsView.setTranslationX(0); animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT)) || (adjacentTask2 != null && adjacentTask2.getGlobalVisibleRect(TEMP_RECT)); + mRecentsView.setTranslationX(prevTranslationX); } } mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate); @@ -701,13 +702,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController(); if (controller != null) { - float offsetX = 0; - if (mRecentsView != null) { - int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild( - mRecentsView.getRunningTaskView())); - offsetX = startScroll - mRecentsView.getScrollX(); - offsetX *= mRecentsView.getScaleX(); - } + float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset(); float offsetScale = getTaskCurveScaleForOffsetX(offsetX, mClipAnimationHelper.getTargetRect().width()); mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale); @@ -751,6 +746,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> ? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart)); } + /** + * @param windowProgress 0 == app, 1 == overview + */ private void updateSysUiFlags(float windowProgress) { if (mRecentsView != null) { TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView @@ -873,9 +871,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> @UiThread private InputConsumer createNewInputProxyHandler() { endRunningWindowAnim(); - if (mLauncherTransitionController != null) { - mLauncherTransitionController.getAnimationPlayer().end(); - } + endLauncherTransitionController(); if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) { // Hide the task view, if not already hidden setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha); @@ -1217,6 +1213,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } + // Make sure recents is in its final state + maybeUpdateRecentsAttachedState(false); + mActivityControlHelper.onSwipeUpToHomeComplete(mActivity); } }); return anim; @@ -1251,7 +1250,17 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> if (!mCanceled) { TaskView nextTask = mRecentsView.getTaskView(taskId); if (nextTask != null) { - nextTask.launchTask(false /* animate */, true /* freezeTaskList */); + nextTask.launchTask(false /* animate */, true /* freezeTaskList */, + success -> { + if (!success) { + // We couldn't launch the task, so take user to overview so they can + // decide what to do instead of staying in this broken state. + endLauncherTransitionController(); + mActivityControlHelper.onLaunchTaskFailed(mActivity); + nextTask.notifyTaskLaunchFailed(TAG); + updateSysUiFlags(1 /* windowProgress == overview */); + } + }, mMainThreadHandler); doLogGesture(NEW_TASK); } reset(); @@ -1314,6 +1323,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> } private void endLauncherTransitionController() { + setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); if (mLauncherTransitionController != null) { mLauncherTransitionController.getAnimationPlayer().end(); mLauncherTransitionController = null; 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 489eb278f..a1e5d47a5 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 @@ -32,6 +32,19 @@ public interface InputConsumer { int TYPE_ACCESSIBILITY = 1 << 5; int TYPE_SCREEN_PINNED = 1 << 6; int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7; + int TYPE_RESET_GESTURE = 1 << 8; + + String[] NAMES = new String[] { + "TYPE_NO_OP", // 0 + "TYPE_OVERVIEW", // 1 + "TYPE_OTHER_ACTIVITY", // 2 + "TYPE_ASSISTANT", // 3 + "TYPE_DEVICE_LOCKED", // 4 + "TYPE_ACCESSIBILITY", // 5 + "TYPE_SCREEN_PINNED", // 6 + "TYPE_OVERVIEW_WITHOUT_FOCUS", // 7 + "TYPE_RESET_GESTURE", // 8 + }; InputConsumer NO_OP = () -> TYPE_NO_OP; @@ -66,23 +79,15 @@ public interface InputConsumer { } default String getName() { - switch (getType()) { - case TYPE_OVERVIEW: - return "OVERVIEW"; - case TYPE_OTHER_ACTIVITY: - return "OTHER_ACTIVITY"; - case TYPE_ASSISTANT: - return "ASSISTANT"; - case TYPE_DEVICE_LOCKED: - return "DEVICE_LOCKED"; - case TYPE_ACCESSIBILITY: - return "ACCESSIBILITY"; - case TYPE_SCREEN_PINNED: - return "SCREEN_PINNED"; - case TYPE_OVERVIEW_WITHOUT_FOCUS: - return "TYPE_OVERVIEW_WITHOUT_FOCUS"; - default: - return "NO_OP"; + String name = ""; + for (int i = 0; i < NAMES.length; i++) { + if ((getType() & (1 << i)) != 0) { + if (name.length() > 0) { + name += ":"; + } + name += NAMES[i]; + } } + return name; } } 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 70ea62796..b021df877 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 @@ -27,7 +27,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.ActivityControlHelper; import com.android.quickstep.OverviewCallbacks; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputMonitorCompat; @@ -114,13 +113,5 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity> mActivity.dispatchKeyEvent(ev); } } - - public static InputConsumer newInstanceWithinActivityBounds( - ActivityControlHelper activityHelper) { - BaseDraggingActivity activity = activityHelper.getCreatedActivity(); - if (activity == null) { - return InputConsumer.NO_OP; - } - return new OverviewInputConsumer(activity, null, true); - } } + diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java new file mode 100644 index 000000000..56cba2192 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.inputconsumers; + +import android.view.MotionEvent; + +import com.android.quickstep.SwipeSharedState; + +/** + * A NO_OP input consumer which also resets any pending gesture + */ +public class ResetGestureInputConsumer implements InputConsumer { + + private final SwipeSharedState mSwipeSharedState; + + public ResetGestureInputConsumer(SwipeSharedState swipeSharedState) { + mSwipeSharedState = swipeSharedState; + } + + @Override + public int getType() { + return TYPE_RESET_GESTURE; + } + + @Override + public void onMotionEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN + && mSwipeSharedState.getActiveListener() != null) { + mSwipeSharedState.clearAllState(); + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java index 19a496346..6dc672ecf 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -192,6 +192,7 @@ public class ClipAnimationHelper { float cornerRadius = 0f; float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width(); if (app.mode == targetSet.targetMode) { + alpha = mTaskAlphaCallback.apply(app, params.targetAlpha); if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL); mTmpMatrix.postTranslate(app.position.x, app.position.y); @@ -208,8 +209,11 @@ public class ClipAnimationHelper { } mCurrentCornerRadius = cornerRadius; } + } else if (targetSet.hasRecents) { + // If home has a different target then recents, reverse anim the + // home target. + alpha = 1 - (progress * params.targetAlpha); } - alpha = mTaskAlphaCallback.apply(app, params.targetAlpha); } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) { crop = null; layer = Integer.MAX_VALUE; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java index 94e704a71..83601e617 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java @@ -49,6 +49,8 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { private final Consumer<SwipeAnimationTargetSet> mOnFinishListener; private RecentsAnimationControllerCompat mController; + private boolean mCancelled; + public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen, Consumer<SwipeAnimationTargetSet> onFinishListener) { mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; @@ -75,11 +77,16 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets, homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen, mOnFinishListener); - Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> { - for (SwipeAnimationListener listener : getListeners()) { - listener.onRecentsAnimationStart(targetSet); - } - }); + + if (mCancelled) { + targetSet.cancelAnimation(); + } else { + Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> { + for (SwipeAnimationListener listener : getListeners()) { + listener.onRecentsAnimationStart(targetSet); + } + }); + } } @Override @@ -99,4 +106,9 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { private SwipeAnimationListener[] getListeners() { return mListeners.toArray(new SwipeAnimationListener[mListeners.size()]); } + + public void cancelListener() { + mCancelled = true; + onAnimationCanceled(false); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java index f5a9e8a05..df9efa247 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java @@ -36,7 +36,6 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { private final boolean mShouldMinimizeSplitScreen; private final Consumer<SwipeAnimationTargetSet> mOnFinishListener; - public final RecentsAnimationControllerCompat controller; public final Rect homeContentInsets; public final Rect minimizedHomeBounds; @@ -103,6 +102,10 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { return controller != null ? controller.screenshotTask(taskId) : null; } + public void cancelAnimation() { + finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); + } + public interface SwipeAnimationListener { void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java index 204dd5687..5aab944a3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -37,7 +37,7 @@ import android.widget.TextView; import androidx.annotation.StringRes; -import com.android.launcher3.Launcher; +import com.android.launcher3.BaseActivity; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -187,12 +187,12 @@ public final class DigitalWellBeingToast extends LinearLayout { mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { - final Launcher launcher = Launcher.getLauncher(getContext()); + final BaseActivity activity = BaseActivity.fromContext(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation( this, 0, 0, getWidth(), getHeight()); - launcher.startActivity(intent, options.toBundle()); - launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, + activity.startActivity(intent, options.toBundle()); + activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " 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 e38a315f8..f66e401f9 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 @@ -892,7 +892,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl mRunningTaskTileHidden = isHidden; TaskView runningTask = getRunningTaskView(); if (runningTask != null) { - runningTask.setAlpha(isHidden ? 0 : mContentAlpha); + runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha); } } @@ -1294,7 +1294,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl for (int i = getTaskViewCount() - 1; i >= 0; i--) { TaskView child = getTaskViewAt(i); if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) { - getChildAt(i).setAlpha(alpha); + child.setStableAlpha(alpha); } } mClearAllButton.setContentAlpha(mContentAlpha); @@ -1676,6 +1676,16 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl return mClearAllButton; } + /** + * @return How many pixels the running task is offset on the x-axis due to the current scrollX. + */ + public float getScrollOffset() { + int startScroll = getScrollForPage(getRunningTaskIndex()); + int offsetX = startScroll - getScrollX(); + offsetX *= getScaleX(); + return offsetX; + } + public Consumer<MotionEvent> getEventDispatcher(RotationMode rotationMode) { if (rotationMode.isTransposed) { Matrix transform = new Matrix(); 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 8b8240d0a..6f10b42fb 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 @@ -252,7 +252,7 @@ public class TaskThumbnailView extends View { } } - protected TaskView getTaskView() { + public TaskView getTaskView() { return (TaskView) getParent(); } 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 bf3e91ff6..694d50190 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 @@ -163,6 +163,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private ObjectAnimator mIconAndDimAnimator; private float mIconScaleAnimStartProgress = 0; private float mFocusTransitionProgress = 1; + private float mStableAlpha = 1; private boolean mShowScreenshot; @@ -353,14 +354,15 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mIconLoadRequest = iconCache.updateIconInBackground(mTask, (task) -> { setIcon(task.icon); - if (isRunningTask()) { + if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) { getRecentsView().updateLiveTileIcon(task.icon); } mDigitalWellBeingToast.initialize( mTask, contentDescription -> { setContentDescription(contentDescription); - if (mDigitalWellBeingToast.getVisibility() == VISIBLE) { + if (mDigitalWellBeingToast.getVisibility() == VISIBLE + && getRecentsView() != null) { getRecentsView().onDigitalWellbeingToastShown(); } }); @@ -468,7 +470,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { setTranslationX(0f); setTranslationY(0f); setTranslationZ(0); - setAlpha(1f); + setAlpha(mStableAlpha); setIconScaleAndDim(1); } @@ -477,6 +479,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { setFullscreenProgress(0); } + public void setStableAlpha(float parentAlpha) { + mStableAlpha = parentAlpha; + setAlpha(mStableAlpha); + } + @Override public void onRecycle() { resetViewTransforms(); @@ -498,6 +505,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA); setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation)); + float fade = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation, 0f, 1f); + mTaskFooterContainer.setAlpha(fade); if (mMenuView != null) { mMenuView.setPosition(getX() - getRecentsView().getScrollX(), getY()); mMenuView.setScaleX(getScaleX()); @@ -716,6 +725,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } public boolean isRunningTask() { + if (getRecentsView() == null) { + return false; + } return this == getRecentsView().getRunningTaskView(); } |