From 45c0918f47b5459435adfe33cce13e86af043fba Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Wed, 29 Jul 2020 23:21:51 -0700 Subject: [PATCH] Merging ub-launcher3-rvc-qpr-dev to rvc-qpr-dev Bug: 162366734 Test: system image builds Change-Id: I6675431b180976798afacc7a99251ae36764a50a Merged-In: Ibff46b3ef7ff89accb459db323f31179adb4ef21 --- AndroidManifest.xml | 2 +- quickstep/AndroidManifest-launcher.xml | 2 +- quickstep/AndroidManifest.xml | 2 +- .../hybridhotseat/HotseatFileLog.java | 5 +- .../hybridhotseat/HotseatRestoreHelper.java | 3 - .../QuickstepAtomicAnimationFactory.java | 4 +- .../NoButtonQuickSwitchTouchController.java | 7 +- .../AppToOverviewAnimationProvider.java | 12 +- .../android/quickstep/BaseSwipeUpHandler.java | 12 +- .../quickstep/BaseSwipeUpHandlerV2.java | 13 +- .../quickstep/FallbackActivityInterface.java | 2 +- .../quickstep/FallbackSwipeHandler.java | 139 ++++++- .../quickstep/LauncherActivityInterface.java | 12 +- .../quickstep/LauncherSwipeHandlerV2.java | 71 ++-- .../quickstep/OverviewCommandHelper.java | 2 +- .../quickstep/SwipeUpAnimationLogic.java | 44 +-- .../android/quickstep/TaskOverlayFactory.java | 36 +- .../quickstep/TouchInteractionService.java | 14 +- .../FallbackRecentsStateController.java | 4 +- .../fallback/FallbackRecentsView.java | 9 +- .../AccessibilityInputConsumer.java | 3 +- .../DeviceLockedInputConsumer.java | 2 +- .../OtherActivityInputConsumer.java | 7 +- .../util/StaggeredWorkspaceAnim.java | 6 +- .../quickstep/util/TaskViewSimulator.java | 10 +- .../quickstep/views/AllAppsEduView.java | 26 +- .../quickstep/views/LauncherRecentsView.java | 2 +- .../quickstep/views/OverviewActionsView.java | 4 +- .../android/quickstep/views/RecentsView.java | 179 +++++++-- .../android/quickstep/views/TaskMenuView.java | 20 +- .../quickstep/views/TaskThumbnailView.java | 7 +- .../com/android/quickstep/views/TaskView.java | 44 ++- quickstep/res/drawable/bg_circle.xml | 20 + .../res/layout/gesture_tutorial_fragment.xml | 54 +-- .../res/layout/overview_actions_container.xml | 4 +- quickstep/res/values-af/strings.xml | 19 +- quickstep/res/values-am/strings.xml | 21 +- quickstep/res/values-ar/strings.xml | 21 +- quickstep/res/values-as/strings.xml | 21 +- quickstep/res/values-az/strings.xml | 19 +- quickstep/res/values-b+sr+Latn/strings.xml | 19 +- quickstep/res/values-be/strings.xml | 19 +- quickstep/res/values-bg/strings.xml | 19 +- quickstep/res/values-bn/strings.xml | 19 +- quickstep/res/values-bs/strings.xml | 21 +- quickstep/res/values-ca/strings.xml | 19 +- quickstep/res/values-cs/strings.xml | 19 +- quickstep/res/values-da/strings.xml | 19 +- quickstep/res/values-de/strings.xml | 23 +- quickstep/res/values-el/strings.xml | 21 +- quickstep/res/values-en-rAU/strings.xml | 19 +- quickstep/res/values-en-rCA/strings.xml | 52 +++ quickstep/res/values-en-rGB/strings.xml | 19 +- quickstep/res/values-en-rIN/strings.xml | 19 +- quickstep/res/values-en-rXC/strings.xml | 52 +++ quickstep/res/values-es-rUS/strings.xml | 21 +- quickstep/res/values-es/strings.xml | 21 +- quickstep/res/values-et/strings.xml | 19 +- quickstep/res/values-eu/strings.xml | 21 +- quickstep/res/values-fa/strings.xml | 21 +- quickstep/res/values-fi/strings.xml | 19 +- quickstep/res/values-fr-rCA/strings.xml | 19 +- quickstep/res/values-fr/strings.xml | 21 +- quickstep/res/values-gl/strings.xml | 19 +- quickstep/res/values-gu/strings.xml | 19 +- quickstep/res/values-hi/strings.xml | 21 +- quickstep/res/values-hr/strings.xml | 19 +- quickstep/res/values-hu/strings.xml | 19 +- quickstep/res/values-hy/strings.xml | 19 +- quickstep/res/values-in/strings.xml | 19 +- quickstep/res/values-is/strings.xml | 19 +- quickstep/res/values-it/strings.xml | 19 +- quickstep/res/values-iw/strings.xml | 19 +- quickstep/res/values-ja/strings.xml | 19 +- quickstep/res/values-ka/strings.xml | 21 +- quickstep/res/values-kk/strings.xml | 21 +- quickstep/res/values-km/strings.xml | 19 +- quickstep/res/values-kn/strings.xml | 19 +- quickstep/res/values-ko/strings.xml | 21 +- quickstep/res/values-ky/strings.xml | 21 +- quickstep/res/values-lo/strings.xml | 19 +- quickstep/res/values-lt/strings.xml | 19 +- quickstep/res/values-lv/strings.xml | 19 +- quickstep/res/values-mk/strings.xml | 21 +- quickstep/res/values-ml/strings.xml | 19 +- quickstep/res/values-mn/strings.xml | 21 +- quickstep/res/values-mr/strings.xml | 19 +- quickstep/res/values-ms/strings.xml | 19 +- quickstep/res/values-my/strings.xml | 19 +- quickstep/res/values-nb/strings.xml | 19 +- quickstep/res/values-ne/strings.xml | 27 +- quickstep/res/values-nl/strings.xml | 19 +- quickstep/res/values-or/strings.xml | 19 +- quickstep/res/values-pa/strings.xml | 21 +- quickstep/res/values-pl/strings.xml | 21 +- quickstep/res/values-pt-rPT/strings.xml | 23 +- quickstep/res/values-pt/strings.xml | 19 +- quickstep/res/values-ro/strings.xml | 19 +- quickstep/res/values-ru/strings.xml | 21 +- quickstep/res/values-si/strings.xml | 19 +- quickstep/res/values-sk/strings.xml | 19 +- quickstep/res/values-sl/strings.xml | 21 +- quickstep/res/values-sq/strings.xml | 21 +- quickstep/res/values-sr/strings.xml | 19 +- quickstep/res/values-sv/strings.xml | 19 +- quickstep/res/values-sw/strings.xml | 19 +- quickstep/res/values-ta/strings.xml | 19 +- quickstep/res/values-te/strings.xml | 21 +- quickstep/res/values-th/strings.xml | 19 +- quickstep/res/values-tl/strings.xml | 19 +- quickstep/res/values-tr/strings.xml | 21 +- quickstep/res/values-uk/strings.xml | 21 +- quickstep/res/values-ur/strings.xml | 21 +- quickstep/res/values-uz/strings.xml | 19 +- quickstep/res/values-vi/strings.xml | 19 +- quickstep/res/values-zh-rCN/strings.xml | 21 +- quickstep/res/values-zh-rHK/strings.xml | 19 +- quickstep/res/values-zh-rTW/strings.xml | 19 +- quickstep/res/values-zu/strings.xml | 19 +- .../quickstep/RecentsActivityTest.java | 8 +- .../launcher3/BaseQuickstepLauncher.java | 13 + .../QuickstepAppTransitionManagerImpl.java | 7 +- .../BaseRecentsViewStateController.java | 6 +- .../quickstep/BaseActivityInterface.java | 6 +- .../RecentsAnimationDeviceState.java | 264 +------------ .../com/android/quickstep/RecentsModel.java | 13 +- .../quickstep/RotationTouchHelper.java | 363 ++++++++++++++++++ .../quickstep/SysUINavigationMode.java | 15 +- .../interaction/NavBarGestureHandler.java | 18 +- .../SwipeUpGestureTutorialController.java | 23 +- .../interaction/TutorialController.java | 3 + .../logging/StatsLogCompatManager.java | 73 +++- .../android/quickstep/util/LayoutUtils.java | 2 +- .../quickstep/util/RecentsOrientedState.java | 16 +- res/layout/floating_surface_view.xml | 19 + res/values-af/strings.xml | 3 +- res/values-am/strings.xml | 3 +- res/values-ar/strings.xml | 3 +- res/values-as/strings.xml | 3 +- res/values-az/strings.xml | 26 +- res/values-b+sr+Latn/strings.xml | 5 +- res/values-be/strings.xml | 5 +- res/values-bg/strings.xml | 27 +- res/values-bn/strings.xml | 3 +- res/values-bs/strings.xml | 28 +- res/values-ca/strings.xml | 3 +- res/values-cs/strings.xml | 3 +- res/values-da/strings.xml | 29 +- res/values-de/strings.xml | 27 +- res/values-el/strings.xml | 5 +- res/values-en-rAU/strings.xml | 3 +- res/values-en-rCA/strings.xml | 148 +++++++ res/values-en-rGB/strings.xml | 3 +- res/values-en-rIN/strings.xml | 3 +- res/values-en-rXC/strings.xml | 148 +++++++ res/values-es-rUS/strings.xml | 29 +- res/values-es/strings.xml | 25 +- res/values-et/strings.xml | 3 +- res/values-eu/strings.xml | 5 +- res/values-fa/strings.xml | 29 +- res/values-fi/strings.xml | 29 +- res/values-fr-rCA/strings.xml | 27 +- res/values-fr/strings.xml | 3 +- res/values-gl/strings.xml | 24 +- res/values-gu/strings.xml | 5 +- res/values-hi/strings.xml | 3 +- res/values-hr/strings.xml | 24 +- res/values-hu/strings.xml | 27 +- res/values-hy/strings.xml | 26 +- res/values-in/strings.xml | 26 +- res/values-is/strings.xml | 25 +- res/values-it/strings.xml | 3 +- res/values-iw/strings.xml | 29 +- res/values-ja/strings.xml | 25 +- res/values-ka/strings.xml | 3 +- res/values-kk/strings.xml | 3 +- res/values-km/strings.xml | 3 +- res/values-kn/strings.xml | 3 +- res/values-ko/strings.xml | 27 +- res/values-ky/strings.xml | 3 +- res/values-lo/strings.xml | 5 +- res/values-lt/strings.xml | 3 +- res/values-lv/strings.xml | 3 +- res/values-mk/strings.xml | 28 +- res/values-ml/strings.xml | 27 +- res/values-mn/strings.xml | 3 +- res/values-mr/strings.xml | 33 +- res/values-ms/strings.xml | 3 +- res/values-my/strings.xml | 5 +- res/values-nb/strings.xml | 25 +- res/values-ne/strings.xml | 3 +- res/values-nl/strings.xml | 3 +- res/values-or/strings.xml | 41 +- res/values-pa/strings.xml | 31 +- res/values-pl/strings.xml | 33 +- res/values-pt-rPT/strings.xml | 3 +- res/values-pt/strings.xml | 3 +- res/values-ro/strings.xml | 3 +- res/values-ru/strings.xml | 27 +- res/values-si/strings.xml | 3 +- res/values-sk/strings.xml | 24 +- res/values-sl/strings.xml | 29 +- res/values-sq/strings.xml | 28 +- res/values-sr/strings.xml | 5 +- res/values-sv/strings.xml | 3 +- res/values-sw/strings.xml | 28 +- res/values-ta/strings.xml | 3 +- res/values-te/strings.xml | 24 +- res/values-th/strings.xml | 24 +- res/values-tl/strings.xml | 3 +- res/values-tr/strings.xml | 3 +- res/values-uk/strings.xml | 3 +- res/values-ur/strings.xml | 3 +- res/values-uz/strings.xml | 33 +- res/values-vi/strings.xml | 5 +- res/values-zh-rCN/strings.xml | 3 +- res/values-zh-rHK/strings.xml | 29 +- res/values-zh-rTW/strings.xml | 3 +- res/values-zu/strings.xml | 3 +- res/values/config.xml | 2 +- .../launcher3/AbstractFloatingView.java | 9 +- .../launcher3/BaseDraggingActivity.java | 2 +- src/com/android/launcher3/BubbleTextView.java | 29 +- .../android/launcher3/GestureNavContract.java | 101 +++++ src/com/android/launcher3/Launcher.java | 19 +- src/com/android/launcher3/LauncherState.java | 3 +- src/com/android/launcher3/PagedView.java | 21 +- src/com/android/launcher3/Workspace.java | 4 +- .../launcher3/config/FeatureFlags.java | 4 + src/com/android/launcher3/folder/Folder.java | 10 +- .../android/launcher3/folder/FolderIcon.java | 16 + .../launcher3/folder/FolderPagedView.java | 3 + .../graphics/LauncherPreviewRenderer.java | 4 +- .../launcher3/logging/StatsLogManager.java | 59 ++- .../launcher3/model/PredictionModel.java | 12 + src/com/android/launcher3/pm/UserCache.java | 5 + .../shortcuts/DeepShortcutTextView.java | 13 +- .../launcher3/testing/TestProtocol.java | 1 + .../touch/LandscapePagedViewHandler.java | 12 +- .../touch/PagedOrientationHandler.java | 4 +- .../touch/PortraitPagedViewHandler.java | 12 +- .../touch/SeascapePagedViewHandler.java | 7 + .../util/MainThreadInitializedObject.java | 2 +- .../android/launcher3/util/TraceHelper.java | 2 +- .../launcher3/views/BaseDragLayer.java | 4 +- .../android/launcher3/views/ClipIconView.java | 58 ++- .../launcher3/views/FloatingIconView.java | 79 ++-- .../launcher3/views/FloatingSurfaceView.java | 241 ++++++++++++ .../launcher3/views/IconLabelDotView.java | 14 + tests/AndroidManifest-common.xml | 2 +- .../com/android/launcher3/ui/WorkTabTest.java | 6 + .../android/launcher3/tapl/Background.java | 6 +- .../tapl/LauncherInstrumentation.java | 23 +- 253 files changed, 4274 insertions(+), 1307 deletions(-) create mode 100644 quickstep/res/drawable/bg_circle.xml create mode 100644 quickstep/res/values-en-rCA/strings.xml create mode 100644 quickstep/res/values-en-rXC/strings.xml create mode 100644 quickstep/src/com/android/quickstep/RotationTouchHelper.java create mode 100644 res/layout/floating_surface_view.xml create mode 100644 res/values-en-rCA/strings.xml create mode 100644 res/values-en-rXC/strings.xml create mode 100644 src/com/android/launcher3/GestureNavContract.java create mode 100644 src/com/android/launcher3/views/FloatingSurfaceView.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b031ffbee4..bc0cd97685 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index 60afddb0a8..d680507e3b 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index e49f2ecdc0..bb83b761e7 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -60,7 +60,7 @@ android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" /> diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java index c15a5963f6..20e1edc05f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java @@ -71,10 +71,9 @@ public class HotseatFileLog { } private PrintWriter getWriter() { - String fName = FILE_NAME_PREFIX + (LOG_DAYS % 10); - if (fName.equals(mFileName)) return mCurrentWriter; - Calendar cal = Calendar.getInstance(); + String fName = FILE_NAME_PREFIX + (cal.get(Calendar.DAY_OF_YEAR) % 10); + if (fName.equals(mFileName)) return mCurrentWriter; boolean append = false; File logFile = new File(mLogsDir, fName); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java index 8c1db4e2e7..9e7c9fba6d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java @@ -30,7 +30,6 @@ import com.android.launcher3.provider.LauncherDbUtils; */ public class HotseatRestoreHelper { private final Launcher mLauncher; - private boolean mBackupRestored = false; HotseatRestoreHelper(Launcher context) { mLauncher = context; @@ -62,7 +61,6 @@ public class HotseatRestoreHelper { * Finds and restores a previously saved snapshow of Favorites table */ public void restoreBackup() { - if (mBackupRestored) return; MODEL_EXECUTOR.execute(() -> { try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction) LauncherSettings.Settings.call( @@ -78,7 +76,6 @@ public class HotseatRestoreHelper { idp.numRows); backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true); transaction.commit(); - mBackupRestored = true; mLauncher.getModel().forceReload(); } }); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index a0af79743b..131fcbfbf1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -17,7 +17,6 @@ package com.android.launcher3.uioverrides.states; import static android.view.View.VISIBLE; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.HINT_STATE; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; @@ -52,6 +51,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import android.animation.Animator; import android.animation.AnimatorSet; @@ -212,7 +212,7 @@ public class QuickstepAtomicAnimationFactory extends // Scale up the recents, if it is not coming from the side RecentsView overview = mActivity.getOverviewPanel(); if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) { - SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); + RECENTS_SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); } } config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index 1b439d1d31..821ada400e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.uioverrides.touchcontrollers; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; @@ -47,6 +46,7 @@ import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE; import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import android.animation.Animator; @@ -244,7 +244,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, final LauncherState toState = OVERVIEW; // Set RecentView's initial properties. - SCALE_PROPERTY.set(mRecentsView, fromState.getOverviewScaleAndOffset(mLauncher)[0]); + RECENTS_SCALE_PROPERTY.set(mRecentsView, fromState.getOverviewScaleAndOffset(mLauncher)[0]); ADJACENT_PAGE_OFFSET.set(mRecentsView, 1f); mRecentsView.setContentAlpha(1); mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress()); @@ -266,7 +266,8 @@ public class NoButtonQuickSwitchTouchController implements TouchController, // - RecentsView scale // - RecentsView fullscreenProgress PendingAnimation yAnim = new PendingAnimation((long) (mYRange * 2)); - yAnim.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndOffset[0], SCALE_DOWN_INTERPOLATOR); + yAnim.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0], + SCALE_DOWN_INTERPOLATOR); yAnim.setFloat(mRecentsView, FULLSCREEN_PROGRESS, toState.getOverviewFullscreenProgress(), SCALE_DOWN_INTERPOLATOR); mYOverviewAnim = yAnim.createPlaybackController(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java index de83caf162..9310685e30 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -24,6 +24,7 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD import android.animation.Animator; import android.animation.AnimatorSet; +import android.app.ActivityManager.RunningTaskInfo; import android.util.Log; import android.view.animation.Interpolator; @@ -52,17 +53,17 @@ final class AppToOverviewAnimationProvider> extend private final BaseActivityInterface mActivityInterface; // The id of the currently running task that is transitioning to overview. - private final int mTargetTaskId; + private final RunningTaskInfo mTargetTask; private final RecentsAnimationDeviceState mDeviceState; private T mActivity; private RecentsView mRecentsView; AppToOverviewAnimationProvider( - BaseActivityInterface activityInterface, int targetTaskId, + BaseActivityInterface activityInterface, RunningTaskInfo targetTask, RecentsAnimationDeviceState deviceState) { mActivityInterface = activityInterface; - mTargetTaskId = targetTaskId; + mTargetTask = targetTask; mDeviceState = deviceState; } @@ -73,7 +74,7 @@ final class AppToOverviewAnimationProvider> extend * @param wasVisible true if it was visible before */ boolean onActivityReady(T activity, Boolean wasVisible) { - activity.getOverviewPanel().showCurrentTask(mTargetTaskId); + activity.getOverviewPanel().showCurrentTask(mTargetTask); AbstractFloatingView.closeAllOpenViews(activity, wasVisible); BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI( mDeviceState, @@ -122,7 +123,8 @@ final class AppToOverviewAnimationProvider> extend wallpaperTargets, MODE_CLOSING); // Use the top closing app to determine the insets for the animation - RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mTargetTaskId); + RemoteAnimationTargetCompat runningTaskTarget = mTargetTask == null ? null + : targets.findTask(mTargetTask.taskId); if (runningTaskTarget == null) { Log.e(TAG, "No closing app"); return pa.buildAnim(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index aba5ab63e1..cbef67b84b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -15,6 +15,8 @@ */ package com.android.quickstep; +import static android.widget.Toast.LENGTH_SHORT; + import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; @@ -27,11 +29,13 @@ import android.graphics.Rect; import android.os.Build; import android.util.Log; import android.view.MotionEvent; +import android.widget.Toast; import androidx.annotation.CallSuper; import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.R; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.VibratorWrapper; @@ -140,10 +144,10 @@ public abstract class BaseSwipeUpHandler, Q extend mRecentsView.getNextPageTaskView().launchTask(false /* animate */, true /* freezeTaskList */); } else { - int taskId = mRecentsView.getNextPageTaskView().getTask().key.id; if (!mCanceled) { - TaskView nextTask = mRecentsView.getTaskView(taskId); + TaskView nextTask = mRecentsView.getNextPageTaskView(); if (nextTask != null) { + int taskId = nextTask.getTask().key.id; mGestureState.updateLastStartedTaskId(taskId); boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId); @@ -160,6 +164,10 @@ public abstract class BaseSwipeUpHandler, Q extend mRecentsAnimationController.finish(true /* toRecents */, null); } }, MAIN_EXECUTOR.getHandler()); + } else { + mActivityInterface.onLaunchTaskFailed(); + Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show(); + mRecentsAnimationController.finish(true /* toRecents */, null); } } mCanceled = false; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index f0f3d0f1e3..758066f8c7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -266,10 +266,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK, this::notifyTransitionCancelled); - mGestureState.runOnceAtState(STATE_END_TARGET_SET, - () -> mDeviceState.onEndTargetCalculated(mGestureState.getEndTarget(), - mActivityInterface)); - if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) { mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT, @@ -337,7 +333,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { return; } - mTaskViewSimulator.setRecentsConfiguration(mActivity.getResources().getConfiguration()); + mTaskViewSimulator.setRecentsRotation(mActivity.getDisplay().getRotation()); // 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. @@ -400,6 +396,11 @@ public abstract class BaseSwipeUpHandlerV2, Q exte mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback( mOnDeferredActivityLaunch); + mGestureState.runOnceAtState(STATE_END_TARGET_SET, + () -> mDeviceState.getRotationTouchHelper(). + onEndTargetCalculated(mGestureState.getEndTarget(), + mActivityInterface)); + notifyGestureStartedAsync(); } @@ -423,7 +424,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } protected void notifyGestureAnimationStartToRecents() { - mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId()); + mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask()); } private void launcherFrameDrawn() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java index 33b9cdee08..d1da0c1c10 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java @@ -140,7 +140,7 @@ public final class FallbackActivityInterface extends } @Override - public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) { + public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { // no-op, fake landscape not supported for 3P } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java index fc7a119f21..f60a50bb43 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java @@ -15,14 +15,35 @@ */ package com.android.quickstep; +import static android.content.Intent.EXTRA_COMPONENT_NAME; +import static android.content.Intent.EXTRA_USER; + +import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT; +import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION; +import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE; +import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; import android.animation.ObjectAnimator; +import android.annotation.TargetApi; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.ParcelUuid; +import android.os.UserHandle; +import android.view.Surface; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; import androidx.annotation.NonNull; @@ -32,19 +53,33 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.quickstep.fallback.FallbackRecentsView; +import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.TransformParams; import com.android.quickstep.util.TransformParams.BuilderProxy; +import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; +import java.lang.ref.WeakReference; +import java.util.UUID; +import java.util.function.Consumer; + /** * Handles the navigation gestures when a 3rd party launcher is the default home activity. */ +@TargetApi(Build.VERSION_CODES.R) public class FallbackSwipeHandler extends BaseSwipeUpHandlerV2 { + /** + * Message used for receiving gesture nav contract information. We use a static messenger to + * avoid leaking too make binders in case the receiving launcher does not handle the contract + * properly. + */ + private static StaticMessageReceiver sMessageReceiver = null; + private FallbackHomeAnimationFactory mActiveAnimationFactory; private final boolean mRunningOverHome; @@ -89,7 +124,9 @@ public class FallbackSwipeHandler extends protected HomeAnimationFactory createHomeAnimationFactory(long duration) { mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); - mContext.startActivity(new Intent(mGestureState.getHomeIntent()), options.toBundle()); + Intent intent = new Intent(mGestureState.getHomeIntent()); + mActiveAnimationFactory.addGestureContract(intent); + mContext.startActivity(intent, options.toBundle()); return mActiveAnimationFactory; } @@ -130,17 +167,20 @@ public class FallbackSwipeHandler extends } private class FallbackHomeAnimationFactory extends HomeAnimationFactory { - + private final Rect mTempRect = new Rect(); private final TransformParams mHomeAlphaParams = new TransformParams(); private final AnimatedFloat mHomeAlpha; private final AnimatedFloat mVerticalShiftForScale = new AnimatedFloat(); - private final AnimatedFloat mRecentsAlpha = new AnimatedFloat(); + private final RectF mTargetRect = new RectF(); + private SurfaceControl mSurfaceControl; + private final long mDuration; + + private RectFSpringAnim mSpringAnim; FallbackHomeAnimationFactory(long duration) { - super(null); mDuration = duration; if (mRunningOverHome) { @@ -162,6 +202,15 @@ public class FallbackSwipeHandler extends this::updateRecentsActivityTransformDuringHomeAnim); } + @NonNull + @Override + public RectF getWindowTargetRect() { + if (mTargetRect.isEmpty()) { + mTargetRect.set(super.getWindowTargetRect()); + } + return mTargetRect; + } + private void updateRecentsActivityTransformDuringHomeAnim(SurfaceParams.Builder builder, RemoteAnimationTargetCompat app, TransformParams params) { builder.withAlpha(mRecentsAlpha.value); @@ -218,5 +267,87 @@ public class FallbackSwipeHandler extends .start(); } } + + @Override + public void setAnimation(RectFSpringAnim anim) { + mSpringAnim = anim; + } + + private void onMessageReceived(Message msg) { + try { + Bundle data = msg.getData(); + RectF position = data.getParcelable(EXTRA_ICON_POSITION); + if (!position.isEmpty()) { + mSurfaceControl = data.getParcelable(EXTRA_ICON_SURFACE); + mTargetRect.set(position); + if (mSpringAnim != null) { + mSpringAnim.onTargetPositionChanged(); + } + } + } catch (Exception e) { + // Ignore + } + } + + @Override + public void update(RectF currentRect, float progress, float radius) { + if (mSurfaceControl != null) { + currentRect.roundOut(mTempRect); + Transaction t = new Transaction(); + t.setGeometry(mSurfaceControl, null, mTempRect, Surface.ROTATION_0); + t.apply(); + } + } + + private void addGestureContract(Intent intent) { + if (mRunningOverHome || mGestureState.getRunningTask() == null) { + return; + } + + TaskKey key = new TaskKey(mGestureState.getRunningTask()); + if (key.getComponent() != null) { + if (sMessageReceiver == null) { + sMessageReceiver = new StaticMessageReceiver(); + } + + Bundle gestureNavContract = new Bundle(); + gestureNavContract.putParcelable(EXTRA_COMPONENT_NAME, key.getComponent()); + gestureNavContract.putParcelable(EXTRA_USER, UserHandle.of(key.userId)); + gestureNavContract.putParcelable(EXTRA_REMOTE_CALLBACK, + sMessageReceiver.newCallback(this::onMessageReceived)); + intent.putExtra(EXTRA_GESTURE_CONTRACT, gestureNavContract); + } + } + } + + private static class StaticMessageReceiver implements Handler.Callback { + + private final Messenger mMessenger = + new Messenger(new Handler(Looper.getMainLooper(), this)); + + private ParcelUuid mCurrentUID = new ParcelUuid(UUID.randomUUID()); + private WeakReference> mCurrentCallback = new WeakReference<>(null); + + public Message newCallback(Consumer callback) { + mCurrentUID = new ParcelUuid(UUID.randomUUID()); + mCurrentCallback = new WeakReference<>(callback); + + Message msg = Message.obtain(); + msg.replyTo = mMessenger; + msg.obj = mCurrentUID; + return msg; + } + + @Override + public boolean handleMessage(@NonNull Message message) { + if (mCurrentUID.equals(message.obj)) { + Consumer consumer = mCurrentCallback.get(); + if (consumer != null) { + consumer.accept(message); + return true; + } + } + return false; + } } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java index edefbe1252..7cd49fe18d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java @@ -105,7 +105,7 @@ public final class LauncherActivityInterface extends // recents, we assume the first task is invisible, making translation off by one task. launcher.getStateManager().reapplyState(); launcher.getRootView().setForceHideBackArrow(false); - notifyRecentsOfOrientation(deviceState); + notifyRecentsOfOrientation(deviceState.getRotationTouchHelper()); } @Override @@ -120,7 +120,7 @@ public final class LauncherActivityInterface extends @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, boolean activityVisible, Consumer callback) { - notifyRecentsOfOrientation(deviceState); + notifyRecentsOfOrientation(deviceState.getRotationTouchHelper()); DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) { @Override public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, @@ -228,7 +228,7 @@ public final class LauncherActivityInterface extends @Override - public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) { + public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { final StateManager stateManager = getCreatedActivity().getStateManager(); stateManager.addStateListener( new StateManager.StateListener() { @@ -244,11 +244,11 @@ public final class LauncherActivityInterface extends }); } - private void notifyRecentsOfOrientation(RecentsAnimationDeviceState deviceState) { + private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) { // reset layout on swipe to home RecentsView recentsView = getCreatedActivity().getOverviewPanel(); - recentsView.setLayoutRotation(deviceState.getCurrentActiveRotation(), - deviceState.getDisplayRotation()); + recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(), + rotationTouchHelper.getDisplayRotation()); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java index fa7d2689f3..052d0a68a6 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -16,6 +16,7 @@ package com.android.quickstep; import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import android.animation.AnimatorSet; import android.content.Context; @@ -28,6 +29,7 @@ import androidx.annotation.NonNull; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.views.FloatingIconView; +import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -72,36 +74,39 @@ public class LauncherSwipeHandlerV2 extends mActivity.getRootView().setForceHideBackArrow(true); mActivity.setHintUserWillBeActive(); - homeAnimFactory = new HomeAnimationFactory(floatingIconView) { - - @Override - public RectF getWindowTargetRect() { - if (canUseWorkspaceView) { + if (canUseWorkspaceView) { + // We want the window alpha to be 0 once this threshold is met, so that the + // FolderIconView can be seen morphing into the icon shape. + float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION; + homeAnimFactory = new LauncherHomeAnimationFactory() { + @Override + public RectF getWindowTargetRect() { return iconLocation; - } else { - return super.getWindowTargetRect(); } - } - @NonNull - @Override - public AnimatorPlaybackController createActivityAnimationToHome() { - // Return an empty APC here since we have an non-user controlled animation - // to home. - long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); - return mActivity.getStateManager().createAnimationToNewWorkspace( - NORMAL, accuracy, 0 /* animComponents */); - } + @Override + public void setAnimation(RectFSpringAnim anim) { + anim.addAnimatorListener(floatingIconView); + floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged); + floatingIconView.setFastFinishRunnable(anim::end); + } - @Override - public void playAtomicAnimation(float velocity) { - new StaggeredWorkspaceAnim(mActivity, velocity, - true /* animateOverviewScrim */).start(); - } - }; + @Override + public void update(RectF currentRect, float progress, float radius) { + floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold, + radius, false); + } + @Override + public void onCancel() { + floatingIconView.fastFinish(); + } + }; + } else { + homeAnimFactory = new LauncherHomeAnimationFactory(); + } } else { - homeAnimFactory = new HomeAnimationFactory(null) { + homeAnimFactory = new HomeAnimationFactory() { @Override public AnimatorPlaybackController createActivityAnimationToHome() { return AnimatorPlaybackController.wrap(new AnimatorSet(), duration); @@ -118,4 +123,22 @@ public class LauncherSwipeHandlerV2 extends mRecentsAnimationController.finish( true /* toRecents */, callback, true /* sendUserLeaveHint */); } + + private class LauncherHomeAnimationFactory extends HomeAnimationFactory { + @NonNull + @Override + public AnimatorPlaybackController createActivityAnimationToHome() { + // Return an empty APC here since we have an non-user controlled animation + // to home. + long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); + return mActivity.getStateManager().createAnimationToNewWorkspace( + NORMAL, accuracy, 0 /* animComponents */); + } + + @Override + public void playAtomicAnimation(float velocity) { + new StaggeredWorkspaceAnim(mActivity, velocity, + true /* animateOverviewScrim */).start(); + } + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java index 434a929b5c..4879db7897 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java @@ -165,7 +165,7 @@ public class OverviewCommandHelper { mActivityInterface = mOverviewComponentObserver.getActivityInterface(); mCreateTime = SystemClock.elapsedRealtime(); mAnimationProvider = new AppToOverviewAnimationProvider<>(mActivityInterface, - RecentsModel.getRunningTaskId(), mDeviceState); + ActivityManagerWrapper.getInstance().getRunningTask(), mDeviceState); // Preload the plan mRecentsModel.getTasks(null); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index dc8f1c54c8..e54a21c073 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -17,7 +17,6 @@ package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; -import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import android.animation.Animator; import android.content.Context; @@ -28,7 +27,6 @@ import android.graphics.RectF; import android.view.animation.Interpolator; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; @@ -37,7 +35,6 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.touch.PagedOrientationHandler; -import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; @@ -85,7 +82,8 @@ public abstract class SwipeUpAnimationLogic { mTransformParams = transformParams; mTaskViewSimulator.setLayoutRotation( - mDeviceState.getCurrentActiveRotation(), mDeviceState.getDisplayRotation()); + mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(), + mDeviceState.getRotationTouchHelper().getDisplayRotation()); } protected void initTransitionEndpoints(DeviceProfile dp) { @@ -148,12 +146,6 @@ public abstract class SwipeUpAnimationLogic { protected abstract class HomeAnimationFactory { - public FloatingIconView mIconView; - - public HomeAnimationFactory(@Nullable FloatingIconView iconView) { - mIconView = iconView; - } - public @NonNull RectF getWindowTargetRect() { PagedOrientationHandler orientationHandler = getOrientationHandler(); DeviceProfile dp = mDp; @@ -174,6 +166,12 @@ public abstract class SwipeUpAnimationLogic { public void playAtomicAnimation(float velocity) { // No-op } + + public void setAnimation(RectFSpringAnim anim) { } + + public void update(RectF currentRect, float progress, float radius) { } + + public void onCancel() { } } /** @@ -184,8 +182,6 @@ public abstract class SwipeUpAnimationLogic { protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); - final FloatingIconView fiv = homeAnimationFactory.mIconView; - final boolean isFloatingIconView = fiv != null; mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor); mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress)); @@ -203,11 +199,7 @@ public abstract class SwipeUpAnimationLogic { windowToHomePositionMap.mapRect(startRect); RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext); - if (isFloatingIconView) { - anim.addAnimatorListener(fiv); - fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); - fiv.setFastFinishRunnable(anim::end); - } + homeAnimationFactory.setAnimation(anim); SpringAnimationRunner runner = new SpringAnimationRunner( homeAnimationFactory, cropRectF, homeToWindowPositionMap); @@ -242,32 +234,27 @@ public abstract class SwipeUpAnimationLogic { final RectF mWindowCurrentRect = new RectF(); final Matrix mHomeToWindowPositionMap; + final HomeAnimationFactory mAnimationFactory; - final FloatingIconView mFIV; final AnimatorPlaybackController mHomeAnim; final RectF mCropRectF; final float mStartRadius; final float mEndRadius; - final float mWindowAlphaThreshold; SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF, Matrix homeToWindowPositionMap) { + mAnimationFactory = factory; mHomeAnim = factory.createActivityAnimationToHome(); mCropRectF = cropRectF; mHomeToWindowPositionMap = homeToWindowPositionMap; cropRectF.roundOut(mCropRect); - mFIV = factory.mIconView; // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. mStartRadius = mTaskViewSimulator.getCurrentCornerRadius(); mEndRadius = cropRectF.width() / 2f; - - // We want the window alpha to be 0 once this threshold is met, so that the - // FolderIconView can be seen morphing into the icon shape. - mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f; } @Override @@ -282,10 +269,7 @@ public abstract class SwipeUpAnimationLogic { .setCornerRadius(cornerRadius); mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this)); - if (mFIV != null) { - mFIV.update(currentRect, 1f, progress, - mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false); - } + mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius)); } @Override @@ -298,9 +282,7 @@ public abstract class SwipeUpAnimationLogic { @Override public void onCancel() { - if (mFIV != null) { - mFIV.fastFinish(); - } + mAnimationFactory.onCancel(); } @Override 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 e9614d1351..db512fa0f9 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -19,6 +19,7 @@ package com.android.quickstep; import static android.view.Surface.ROTATION_0; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; +import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL; import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED; import android.annotation.SuppressLint; @@ -146,26 +147,29 @@ public class TaskOverlayFactory implements ResourceBasedOverride { */ public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix, boolean rotated) { - final boolean isAllowedByPolicy = thumbnail.isRealSnapshot; + getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null); - getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); + if (thumbnail != null) { + getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); + final boolean isAllowedByPolicy = thumbnail.isRealSnapshot; - getActionsView().setCallbacks(new OverlayUICallbacks() { - @Override - public void onShare() { - if (isAllowedByPolicy) { - mImageApi.startShareActivity(); - } else { - showBlockedByPolicyMessage(); + getActionsView().setCallbacks(new OverlayUICallbacks() { + @Override + public void onShare() { + if (isAllowedByPolicy) { + mImageApi.startShareActivity(); + } else { + showBlockedByPolicyMessage(); + } } - } - @SuppressLint("NewApi") - @Override - public void onScreenshot() { - saveScreenshot(task); - } - }); + @SuppressLint("NewApi") + @Override + public void onScreenshot() { + saveScreenshot(task); + } + }); + } } /** 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 6e0b517b25..13adff53f3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -258,6 +258,7 @@ public class TouchInteractionService extends Service implements PluginListener mAM.getRunningTask(false /* filterOnlyVisibleRecents */))); } return gestureState; @@ -660,7 +662,7 @@ public class TouchInteractionService extends Service implements PluginListener mAM.getRunningTask(true /* filterOnlyVisibleRecents */))); ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent(); ComponentName runningComponent = diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 3f1e7bad9b..163c23268b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -15,7 +15,6 @@ */ package com.android.quickstep.fallback; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; @@ -25,6 +24,7 @@ import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVER import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; import com.android.launcher3.anim.PendingAnimation; @@ -82,7 +82,7 @@ public class FallbackRecentsStateController implements StateHandler */ public void onGestureAnimationStartOnHome(RunningTaskInfo homeTaskInfo) { mHomeTaskInfo = homeTaskInfo; - onGestureAnimationStart(homeTaskInfo == null ? -1 : homeTaskInfo.taskId); + onGestureAnimationStart(homeTaskInfo); } /** @@ -107,14 +107,15 @@ public class FallbackRecentsView extends RecentsView } @Override - protected boolean shouldAddDummyTaskView(int runningTaskId) { - if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId + protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) { + if (mHomeTaskInfo != null && runningTaskInfo != null && + mHomeTaskInfo.taskId == runningTaskInfo.taskId && getTaskViewCount() == 0) { // Do not add a dummy task if we are running over home with empty recents, so that we // show the empty recents message instead of showing a dummy task and later removing it. return false; } - return super.shouldAddDummyTaskView(runningTaskId); + return super.shouldAddDummyTaskView(runningTaskInfo); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java index 5ad48ebabc..0c2c92cfb0 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java @@ -99,7 +99,8 @@ public class AccessibilityInputConsumer extends DelegateInputConsumer { case ACTION_POINTER_DOWN: { if (mState == STATE_INACTIVE) { int pointerIndex = ev.getActionIndex(); - if (mDeviceState.isInSwipeUpTouchRegion(ev, pointerIndex) + if (mDeviceState.getRotationTouchHelper() + .isInSwipeUpTouchRegion(ev, pointerIndex) && mDelegate.allowInterceptByParent()) { setActive(ev); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java index 3a97216035..a676390ce3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java @@ -147,7 +147,7 @@ public class DeviceLockedInputConsumer implements InputConsumer, if (!mThresholdCrossed) { // Cancel interaction in case of multi-touch interaction int ptrIdx = ev.getActionIndex(); - if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) { + if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx)) { int action = ev.getAction(); ev.setAction(ACTION_CANCEL); finishTouchTracking(ev); 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 26df9c7b93..6259f1f9fe 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 @@ -59,6 +59,7 @@ import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationDeviceState; +import com.android.quickstep.RotationTouchHelper; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.CachedEventDispatcher; @@ -86,6 +87,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC private final NavBarPosition mNavBarPosition; private final TaskAnimationManager mTaskAnimationManager; private final GestureState mGestureState; + private final RotationTouchHelper mRotationTouchHelper; private RecentsAnimationCallbacks mActiveCallbacks; private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher(); private final InputMonitorCompat mInputMonitorCompat; @@ -163,6 +165,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture; mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe; + mRotationTouchHelper = mDeviceState.getRotationTouchHelper(); } @Override @@ -230,7 +233,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC if (!mPassedPilferInputSlop) { // Cancel interaction in case of multi-touch interaction int ptrIdx = ev.getActionIndex(); - if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) { + if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx)) { forceCancelGesture(ev); } } @@ -424,7 +427,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC @Override public void notifyOrientationSetup() { - mDeviceState.onStartGesture(); + mRotationTouchHelper.onStartGesture(); } @Override 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 3cafd423ca..41203319b1 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 @@ -205,13 +205,15 @@ public class StaggeredWorkspaceAnim { ResourceProvider rp = DynamicResource.provider(v.getContext()); float stiffness = rp.getFloat(R.dimen.staggered_stiffness); float damping = rp.getFloat(R.dimen.staggered_damping_ratio); + float endTransY = 0; + float springVelocity = Math.abs(mVelocity) * Math.signum(endTransY - mSpringTransY); ValueAnimator springTransY = new SpringAnimationBuilder(v.getContext()) .setStiffness(stiffness) .setDampingRatio(damping) .setMinimumVisibleChange(1f) .setStartValue(mSpringTransY) - .setEndValue(0) - .setStartVelocity(mVelocity) + .setEndValue(endTransY) + .setStartVelocity(springVelocity) .build(v, VIEW_TRANSLATE_Y); springTransY.setStartDelay(startDelay); springTransY.addListener(new AnimatorListenerAdapter() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java index c9ed498af1..c5918fed84 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java @@ -31,7 +31,6 @@ import android.graphics.RectF; import android.util.IntProperty; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.touch.PagedOrientationHandler; @@ -92,7 +91,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { public final AnimatedFloat recentsViewScale = new AnimatedFloat(); public final AnimatedFloat fullScreenProgress = new AnimatedFloat(); private final ScrollState mScrollState = new ScrollState(); - private final int mPageSpacing; // Cached calculations private boolean mLayoutValid = false; @@ -106,7 +104,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mOrientationState.setGestureActive(true); mCurrentFullscreenParams = new FullscreenDrawParams(context); - mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing); } /** @@ -129,8 +126,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { /** * @see com.android.quickstep.views.RecentsView#onConfigurationChanged(Configuration) */ - public void setRecentsConfiguration(Configuration configuration) { - mOrientationState.setActivityConfiguration(configuration); + public void setRecentsRotation(int recentsRotation) { + mOrientationState.setRecentsRotation(recentsRotation); mLayoutValid = false; } @@ -252,7 +249,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { int start = mOrientationState.getOrientationHandler() .getPrimaryValue(mTaskRect.left, mTaskRect.top); mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize; - mScrollState.updateInterpolation(start, mPageSpacing); + mScrollState.pageParentScale = recentsViewScale.value; + mScrollState.updateInterpolation(start); mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java index 0979c071bb..c06dd9c0bd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java @@ -16,6 +16,7 @@ package com.android.quickstep.views; import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; @@ -42,8 +43,10 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.util.Themes; @@ -51,6 +54,7 @@ import com.android.quickstep.util.MultiValueUpdateListener; /** * View used to educate the user on how to access All Apps when in No Nav Button navigation mode. + * Consumes all touches until after the animation is completed and the view is removed. */ public class AllAppsEduView extends AbstractFloatingView { @@ -110,9 +114,19 @@ public class AllAppsEduView extends AbstractFloatingView { return (type & TYPE_ALL_APPS_EDU) != 0; } + @Override + public boolean onBackPressed() { + return true; + } + + @Override + public boolean canInterceptEventsInSystemGestureRegion() { + return true; + } + @Override public boolean onControllerInterceptTouchEvent(MotionEvent ev) { - return mAnimation != null && mAnimation.isRunning(); + return true; } private void playAnimation() { @@ -139,7 +153,12 @@ public class AllAppsEduView extends AbstractFloatingView { config.userControlled = false; AnimatorPlaybackController stateAnimationController = mLauncher.getStateManager().createAnimationToNewWorkspace(ALL_APPS, config); - float maxAllAppsProgress = 0.15f; + float maxAllAppsProgress = mLauncher.getDeviceProfile().isLandscape ? 0.35f : 0.15f; + + AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); + PendingAnimation allAppsAlpha = new PendingAnimation(config.duration); + allAppsController.setAlphas(ALL_APPS, config, allAppsAlpha); + mAnimation.play(allAppsAlpha.buildAnim()); ValueAnimator intro = ValueAnimator.ofFloat(0, 1f); intro.setInterpolator(LINEAR); @@ -191,7 +210,8 @@ public class AllAppsEduView extends AbstractFloatingView { @Override public void onAnimationEnd(Animator animation) { mAnimation = null; - stateAnimationController.dispatchOnCancel(); + // Handles cancelling the animation used to hint towards All Apps. + mLauncher.getStateManager().goToState(NORMAL, false); handleClose(false); } }); 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 846b94463f..79028d1cc2 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 @@ -189,7 +189,7 @@ public class LauncherRecentsView extends RecentsView @Override public boolean shouldUseMultiWindowTaskSizeStrategy() { - return TraceHelper.whitelistIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode); + return TraceHelper.allowIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index a2da39855c..79d57c55a2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -70,12 +70,14 @@ public class OverviewActionsView extends FrameLayo @IntDef(flag = true, value = { DISABLED_SCROLLING, - DISABLED_ROTATED}) + DISABLED_ROTATED, + DISABLED_NO_THUMBNAIL}) @Retention(RetentionPolicy.SOURCE) public @interface ActionsDisabledFlags { } public static final int DISABLED_SCROLLING = 1 << 0; public static final int DISABLED_ROTATED = 1 << 1; + public static final int DISABLED_NO_THUMBNAIL = 1 << 2; private static final int INDEX_CONTENT_ALPHA = 0; private static final int INDEX_VISIBILITY_ALPHA = 1; 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 7b24b03f2b..857a020698 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 @@ -22,7 +22,6 @@ import static android.view.View.MeasureSpec.makeMeasureSpec; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; @@ -55,15 +54,14 @@ import android.animation.LayoutTransition.TransitionListener; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; -import android.app.ActivityManager; -import android.content.ComponentName; +import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; @@ -80,6 +78,7 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.TouchDelegate; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; @@ -135,6 +134,7 @@ import com.android.quickstep.util.TransformParams; import com.android.systemui.plugins.ResourceProvider; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.recents.model.Task; +import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.LauncherEventUtil; @@ -147,7 +147,7 @@ import java.util.function.Consumer; /** * A list of recent tasks. */ -@TargetApi(Build.VERSION_CODES.P) +@TargetApi(Build.VERSION_CODES.R) public abstract class RecentsView extends PagedView implements Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener, @@ -210,6 +210,23 @@ public abstract class RecentsView extends PagedView } }; + /** Same as normal SCALE_PROPERTY, but also updates page offsets that depend on this scale. */ + public static final FloatProperty RECENTS_SCALE_PROPERTY = + new FloatProperty("recentsScale") { + @Override + public void setValue(RecentsView view, float scale) { + view.setScaleX(scale); + view.setScaleY(scale); + view.mLastComputedTaskPushOutDistance = null; + view.updatePageOffsets(); + } + + @Override + public Float get(RecentsView view) { + return view.getScaleX(); + } + }; + protected RecentsOrientedState mOrientationState; protected final BaseActivityInterface mSizeStrategy; protected RecentsAnimationController mRecentsAnimationController; @@ -217,8 +234,12 @@ public abstract class RecentsView extends PagedView protected SurfaceTransactionApplier mSyncTransactionApplier; protected int mTaskWidth; protected int mTaskHeight; + protected final Rect mLastComputedTaskSize = new Rect(); + // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot. + protected Float mLastComputedTaskPushOutDistance = null; protected boolean mEnableDrawingLiveTile = false; protected final Rect mTempRect = new Rect(); + protected final RectF mTempRectF = new RectF(); private final PointF mTempPointF = new PointF(); private static final int DISMISS_TASK_DURATION = 300; @@ -377,7 +398,7 @@ public abstract class RecentsView extends PagedView mOrientationState.setMultiWindowMode(inMultiWindowMode); setLayoutRotation(mOrientationState.getTouchRotation(), mOrientationState.getDisplayRotation()); - rotateAllChildTasks(); + updateChildTaskOrientations(); } if (!inMultiWindowMode && mOverviewStateEnabled) { // TODO: Re-enable layout transitions for addition of the unpinned task @@ -394,7 +415,7 @@ public abstract class RecentsView extends PagedView mActivity = BaseActivity.fromContext(context); mOrientationState = new RecentsOrientedState( context, mSizeStrategy, this::animateRecentsRotationInPlace); - mOrientationState.setActivityConfiguration(context.getResources().getConfiguration()); + mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation()); mFastFlingVelocity = getResources() .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); @@ -649,6 +670,16 @@ public abstract class RecentsView extends PagedView @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); + + TaskView taskView = getCurrentPageTaskView(); + if (taskView != null) { + TouchDelegate mChildTouchDelegate = taskView.getIconTouchDelegate(ev); + if (mChildTouchDelegate != null && mChildTouchDelegate.onTouchEvent(ev)) { + // Keep consuming events to pass to delegate + return true; + } + } + final int x = (int) ev.getX(); final int y = (int) ev.getY(); switch (ev.getAction()) { @@ -865,6 +896,7 @@ public abstract class RecentsView extends PagedView public void getTaskSize(Rect outRect) { mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect, mOrientationHandler); + mLastComputedTaskSize.set(outRect); } /** Gets the task size for modal state. */ @@ -906,8 +938,8 @@ public abstract class RecentsView extends PagedView final int pageCount = getPageCount(); for (int i = 0; i < pageCount; i++) { View page = getPageAt(i); - mScrollState.updateInterpolation(mOrientationHandler.getChildStartWithTranslation(page), - mPageSpacing); + mScrollState.updateInterpolation( + mOrientationHandler.getChildStartWithTranslation(page)); ((PageCallbacks) page).onPageScroll(mScrollState); } } @@ -1041,13 +1073,13 @@ public abstract class RecentsView extends PagedView /** * Called when a gesture from an app is starting. */ - public void onGestureAnimationStart(int runningTaskId) { + public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) { // This needs to be called before the other states are set since it can create the task view if (mOrientationState.setGestureActive(true)) { updateOrientationHandler(); } - showCurrentTask(runningTaskId); + showCurrentTask(runningTaskInfo); setEnableFreeScroll(false); setEnableDrawingLiveTile(false); setRunningTaskHidden(true); @@ -1078,7 +1110,7 @@ public abstract class RecentsView extends PagedView pa.addListener(AnimationSuccessListener.forRunnable(() -> { setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); mActivity.getDragLayer().recreateControllers(); - rotateAllChildTasks(); + updateChildTaskOrientations(); setRecentsChangedOrientation(false).start(); })); pa.start(); @@ -1099,7 +1131,7 @@ public abstract class RecentsView extends PagedView } - private void rotateAllChildTasks() { + private void updateChildTaskOrientations() { for (int i = 0; i < getTaskViewCount(); i++) { getTaskViewAt(i).setOrientationState(mOrientationState); } @@ -1127,8 +1159,8 @@ public abstract class RecentsView extends PagedView /** * Returns true if we should add a dummy taskView for the running task id */ - protected boolean shouldAddDummyTaskView(int runningTaskId) { - return getTaskView(runningTaskId) == null; + protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) { + return runningTaskInfo != null && getTaskView(runningTaskInfo.taskId) == null; } /** @@ -1137,8 +1169,8 @@ public abstract class RecentsView extends PagedView * All subsequent calls to reload will keep the task as the first item until {@link #reset()} * is called. Also scrolls the view to this task. */ - public void showCurrentTask(int runningTaskId) { - if (shouldAddDummyTaskView(runningTaskId)) { + public void showCurrentTask(RunningTaskInfo runningTaskInfo) { + if (shouldAddDummyTaskView(runningTaskInfo)) { boolean wasEmpty = getChildCount() == 0; // Add an empty view for now until the task plan is loaded and applied final TaskView taskView = mTaskViewPool.getView(); @@ -1148,10 +1180,7 @@ public abstract class RecentsView extends PagedView } // The temporary running task is only used for the duration between the start of the // gesture and the task list is loaded and applied - mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(), - new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0, - false, true, false, false, new ActivityManager.TaskDescription(), 0, - new ComponentName("", ""), false); + mTmpRunningTask = Task.from(new TaskKey(runningTaskInfo), runningTaskInfo, false); taskView.bind(mTmpRunningTask, mOrientationState); // Measure and layout immediately so that the scroll values is updated instantly @@ -1162,7 +1191,7 @@ public abstract class RecentsView extends PagedView } boolean runningTaskTileHidden = mRunningTaskTileHidden; - setCurrentTask(runningTaskId); + setCurrentTask(runningTaskInfo == null ? -1 : runningTaskInfo.taskId); setCurrentPage(getRunningTaskIndex()); setRunningTaskViewShowScreenshot(false); setRunningTaskHidden(runningTaskTileHidden); @@ -1332,10 +1361,14 @@ public abstract class RecentsView extends PagedView /** * Updates linearInterpolation for the provided child position */ - public void updateInterpolation(float childStart, int pageSpacing) { - float pageCenter = childStart + halfPageSize; + public void updateInterpolation(float childStart) { + float scaledHalfPageSize = halfPageSize / pageParentScale; + float pageCenter = childStart + scaledHalfPageSize; float distanceFromScreenCenter = screenCenter - pageCenter; - float distanceToReachEdge = halfScreenSize + halfPageSize + pageSpacing; + // How far the page has to move from the center to be offscreen, taking into account + // the EDGE_SCALE_DOWN_FACTOR that will be applied at that position. + float distanceToReachEdge = halfScreenSize + + scaledHalfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); linearInterpolation = Math.min(1, Math.abs(distanceFromScreenCenter) / distanceToReachEdge); } @@ -1652,13 +1685,16 @@ public abstract class RecentsView extends PagedView super.setVisibility(visibility); if (mActionsView != null) { mActionsView.updateHiddenFlags(HIDDEN_NO_RECENTS, visibility != VISIBLE); + if (visibility != VISIBLE) { + mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false); + } } } @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - if (mOrientationState.setActivityConfiguration(newConfig)) { + if (mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation())) { updateOrientationHandler(); } } @@ -1680,10 +1716,11 @@ public abstract class RecentsView extends PagedView : View.LAYOUT_DIRECTION_RTL); mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated()); mActivity.getDragLayer().recreateControllers(); - boolean isInLandscape = mOrientationState.getTouchRotation() != 0 + boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0 || mOrientationState.getRecentsActivityRotation() != ROTATION_0; mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, !mOrientationState.canRecentsActivityRotate() && isInLandscape); + updateChildTaskOrientations(); resetPaddingFromTaskSize(); requestLayout(); // Reapply the current page to update page scrolls. @@ -1769,14 +1806,15 @@ public abstract class RecentsView extends PagedView setPivotX(mTempPointF.x); setPivotY(mTempPointF.y); setTaskModalness(mTaskModalness); + mLastComputedTaskPushOutDistance = null; updatePageOffsets(); setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO : IMPORTANT_FOR_ACCESSIBILITY_AUTO); } private void updatePageOffsets() { - float offset = mAdjacentPageOffset * getWidth(); - float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness) * getWidth(); + float offset = mAdjacentPageOffset; + float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness); if (mIsRtl) { offset = -offset; modalOffset = -modalOffset; @@ -1785,18 +1823,89 @@ public abstract class RecentsView extends PagedView TaskView runningTask = mRunningTaskId == -1 || !mRunningTaskTileHidden ? null : getTaskView(mRunningTaskId); - int midPoint = runningTask == null ? -1 : indexOfChild(runningTask); - int currentPage = getCurrentPage(); + int midpoint = runningTask == null ? -1 : indexOfChild(runningTask); + int modalMidpoint = getCurrentPage(); + + float midpointOffsetSize = 0; + float leftOffsetSize = midpoint - 1 >= 0 + ? -getOffsetSize(midpoint - 1, midpoint, offset) + : 0; + float rightOffsetSize = midpoint + 1 < count + ? getOffsetSize(midpoint + 1, midpoint, offset) + : 0; + + float modalMidpointOffsetSize = 0; + float modalLeftOffsetSize = modalMidpoint - 1 >= 0 + ? -getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset) + : 0; + float modalRightOffsetSize = modalMidpoint + 1 < count + ? getOffsetSize(modalMidpoint + 1, modalMidpoint, modalOffset) + : 0; for (int i = 0; i < count; i++) { - float translation = i == midPoint ? 0 : (i < midPoint ? -offset : offset); - float modalTranslation = - i == currentPage ? 0 : (i < currentPage ? -modalOffset : modalOffset); + float translation = i == midpoint + ? midpointOffsetSize + : i < midpoint + ? leftOffsetSize + : rightOffsetSize; + float modalTranslation = i == modalMidpoint + ? modalMidpointOffsetSize + : i < modalMidpoint + ? modalLeftOffsetSize + : modalRightOffsetSize; getChildAt(i).setTranslationX(translation + modalTranslation); } updateCurveProperties(); } + /** + * Computes the distance to offset the given child such that it is completely offscreen when + * translating away from the given midpoint. + * @param offsetProgress From 0 to 1 where 0 means no offset and 1 means offset offscreen. + */ + private float getOffsetSize(int childIndex, int midpointIndex, float offsetProgress) { + if (offsetProgress == 0) { + // Don't bother calculating everything below if we won't offset anyway. + return 0; + } + // First, get the position of the task relative to the midpoint. If there is no midpoint + // then we just use the normal (centered) task position. + mTempRectF.set(mLastComputedTaskSize); + RectF taskPosition = mTempRectF; + float desiredLeft = getWidth(); + float distanceToOffscreen = desiredLeft - taskPosition.left; + // Used to calculate the scale of the task view based on its new offset. + float centerToOffscreenProgress = Math.abs(offsetProgress); + if (midpointIndex > -1) { + // When there is a midpoint reference task, adjacent tasks have less distance to travel + // to reach offscreen. Offset the task position to the task's starting point. + View child = getChildAt(childIndex); + View midpointChild = getChildAt(midpointIndex); + int distanceFromMidpoint = Math.abs(mOrientationHandler.getChildStart(child) + - mOrientationHandler.getChildStart(midpointChild) + + getDisplacementFromScreenCenter(midpointIndex)); + taskPosition.offset(distanceFromMidpoint, 0); + centerToOffscreenProgress = Utilities.mapRange(centerToOffscreenProgress, + distanceFromMidpoint / distanceToOffscreen, 1); + } + // Find the task's scale based on its offscreen progress, then see how far it still needs to + // move to be completely offscreen. + Utilities.scaleRectFAboutCenter(taskPosition, + TaskView.getCurveScaleForInterpolation(centerToOffscreenProgress)); + distanceToOffscreen = desiredLeft - taskPosition.left; + // Finally, we need to account for RecentsView scale, because it moves tasks based on its + // pivot. To do this, we move the task position to where it would be offscreen at scale = 1 + // (computed above), then we apply the scale via getMatrix() to determine how much that + // moves the task from its desired position, and adjust the computed distance accordingly. + if (mLastComputedTaskPushOutDistance == null) { + taskPosition.offsetTo(desiredLeft, 0); + getMatrix().mapRect(taskPosition); + mLastComputedTaskPushOutDistance = (taskPosition.left - desiredLeft) / getScaleX(); + } + distanceToOffscreen -= mLastComputedTaskPushOutDistance; + return distanceToOffscreen * offsetProgress; + } + /** * TODO: Do not assume motion across X axis for adjacent page */ @@ -1895,7 +2004,7 @@ public abstract class RecentsView extends PagedView float toScale = getMaxScaleForFullScreen(); if (launchingCenterTask) { RecentsView recentsView = tv.getRecentsView(); - anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale)); + anim.play(ObjectAnimator.ofFloat(recentsView, RECENTS_SCALE_PROPERTY, toScale)); anim.play(ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS, 1)); } else { // We are launching an adjacent task, so parallax the center and other adjacent task. 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 ef66b7a396..8b49f2c212 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 @@ -169,7 +169,9 @@ public class TaskMenuView extends AbstractFloatingView { } if (mIsOpen) { mOptionLayout.removeAllViews(); - populateAndLayoutMenu(); + if (!populateAndLayoutMenu()) { + close(false); + } } } @@ -186,14 +188,22 @@ public class TaskMenuView extends AbstractFloatingView { } mActivity.getDragLayer().addView(this); mTaskView = taskView; - populateAndLayoutMenu(); + if (!populateAndLayoutMenu()) { + return false; + } post(this::animateOpen); return true; } - private void populateAndLayoutMenu() { + /** @return true if successfully able to populate task view menu, false otherwise */ + private boolean populateAndLayoutMenu() { + if (mTaskView.getTask().icon == null) { + // Icon may not be loaded + return false; + } addMenuOptions(mTaskView); orientAroundTaskView(mTaskView); + return true; } private void addMenuOptions(TaskView taskView) { @@ -240,8 +250,10 @@ public class TaskMenuView extends AbstractFloatingView { setLayoutParams(params); setScaleX(taskView.getScaleX()); setScaleY(taskView.getScaleY()); + boolean canActivityRotate = taskView.getRecentsView() + .mOrientationState.canRecentsActivityRotate(); mOptionLayout.setOrientation(orientationHandler - .getTaskMenuLayoutOrientation(mOptionLayout)); + .getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout)); setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top, taskView.getPagedOrientationHandler()); } 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 b2f937f8c2..a8d6442135 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 @@ -59,7 +59,6 @@ import com.android.systemui.plugins.OverviewScreenshotActions; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.ConfigurationCompat; /** * A task in the Recents view. @@ -357,7 +356,7 @@ public class TaskThumbnailView extends View implements PluginListener SYSTEM_GESTURE_EXCLUSION_RECT = Collections.singletonList(new Rect()); @@ -186,6 +199,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private int mStackHeight; private View mContextualChipWrapper; private View mContextualChip; + private final float[] mIconCenterCoords = new float[2]; public TaskView(Context context) { this(context, null); @@ -246,6 +260,26 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); + mIconTouchDelegate = new TransformingTouchDelegate(mIconView); + } + + public TouchDelegate getIconTouchDelegate(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + computeAndSetIconTouchDelegate(); + } + return mIconTouchDelegate; + } + + private void computeAndSetIconTouchDelegate() { + float iconHalfSize = mIconView.getWidth() / 2f; + mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize; + getDescendantCoordRelativeToAncestor(mIconView, mActivity.getDragLayer(), mIconCenterCoords, + false); + mIconTouchDelegate.setBounds( + (int) (mIconCenterCoords[0] - iconHalfSize), + (int) (mIconCenterCoords[1] - iconHalfSize), + (int) (mIconCenterCoords[0] + iconHalfSize), + (int) (mIconCenterCoords[1] + iconHalfSize)); } /** @@ -468,18 +502,18 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin); LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams(); switch (orientationHandler.getRotation()) { - case Surface.ROTATION_90: + case ROTATION_90: iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL; iconParams.rightMargin = -thumbnailPadding; iconParams.leftMargin = 0; iconParams.topMargin = snapshotParams.topMargin / 2; break; - case Surface.ROTATION_180: + case ROTATION_180: iconParams.gravity = BOTTOM | CENTER_HORIZONTAL; iconParams.bottomMargin = -thumbnailPadding; iconParams.leftMargin = iconParams.topMargin = iconParams.rightMargin = 0; break; - case Surface.ROTATION_270: + case ROTATION_270: iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL; iconParams.leftMargin = -thumbnailPadding; iconParams.rightMargin = 0; diff --git a/quickstep/res/drawable/bg_circle.xml b/quickstep/res/drawable/bg_circle.xml new file mode 100644 index 0000000000..506177b6a1 --- /dev/null +++ b/quickstep/res/drawable/bg_circle.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml index 459d65faf7..43bf0ea966 100644 --- a/quickstep/res/layout/gesture_tutorial_fragment.xml +++ b/quickstep/res/layout/gesture_tutorial_fragment.xml @@ -24,6 +24,14 @@ android:layout_height="match_parent" android:background="@drawable/gesture_tutorial_ripple"/> + + + android:padding="18dp" + android:src="@drawable/gesture_tutorial_close_button" + android:tint="?android:attr/textColorPrimary"/> + android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"/> + android:layout_marginTop="10dp" + android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"/> + android:layout_marginBottom="10dp"/>