From 49f25681efc7f88f9ead267779acaedba6f05d63 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Tue, 16 Nov 2021 14:30:23 -0500 Subject: [PATCH 01/11] Make action optional for snackbar. Test: Manual Bug: 188222480 Change-Id: I923dcf50633d8ba751d86095f43e97563a53b692 --- src/com/android/launcher3/views/Snackbar.java | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/com/android/launcher3/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java index 49fcd2ebde..f945819c8d 100644 --- a/src/com/android/launcher3/views/Snackbar.java +++ b/src/com/android/launcher3/views/Snackbar.java @@ -28,8 +28,9 @@ import android.view.Gravity; import android.view.MotionEvent; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.compat.AccessibilityManagerCompat; @@ -44,7 +45,7 @@ public class Snackbar extends AbstractFloatingView { private static final long HIDE_DURATION_MS = 180; private static final int TIMEOUT_DURATION_MS = 4000; - private final BaseDraggingActivity mActivity; + private final ActivityContext mActivity; private Runnable mOnDismissed; public Snackbar(Context context, AttributeSet attrs) { @@ -53,12 +54,19 @@ public class Snackbar extends AbstractFloatingView { public Snackbar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mActivity = BaseDraggingActivity.fromContext(context); + mActivity = ActivityContext.lookupContext(context); inflate(context, R.layout.snackbar, this); } - public static void show(BaseDraggingActivity activity, int labelStringResId, - int actionStringResId, Runnable onDismissed, Runnable onActionClicked) { + /** Show a snackbar with just a label. */ + public static void show(T activity, int labelStringRedId, + Runnable onDismissed) { + show(activity, labelStringRedId, NO_ID, onDismissed, null); + } + + /** Show a snackbar with a label and action. */ + public static void show(T activity, int labelStringResId, + int actionStringResId, Runnable onDismissed, @Nullable Runnable onActionClicked) { closeOpenViews(activity, true, TYPE_SNACKBAR); Snackbar snackbar = new Snackbar(activity, null); // Set some properties here since inflated xml only contains the children. @@ -87,13 +95,30 @@ public class Snackbar extends AbstractFloatingView { params.setMargins(0, 0, 0, marginBottom + insets.bottom); TextView labelView = snackbar.findViewById(R.id.label); - TextView actionView = snackbar.findViewById(R.id.action); String labelText = res.getString(labelStringResId); - String actionText = res.getString(actionStringResId); - int totalContentWidth = (int) (labelView.getPaint().measureText(labelText) - + actionView.getPaint().measureText(actionText)) + labelView.setText(labelText); + + TextView actionView = snackbar.findViewById(R.id.action); + float actionWidth; + if (actionStringResId != NO_ID) { + String actionText = res.getString(actionStringResId); + actionWidth = actionView.getPaint().measureText(actionText) + + actionView.getPaddingRight() + actionView.getPaddingLeft(); + actionView.setText(actionText); + actionView.setOnClickListener(v -> { + if (onActionClicked != null) { + onActionClicked.run(); + } + snackbar.mOnDismissed = null; + snackbar.close(true); + }); + } else { + actionWidth = 0; + actionView.setVisibility(GONE); + } + + int totalContentWidth = (int) (labelView.getPaint().measureText(labelText) + actionWidth) + labelView.getPaddingRight() + labelView.getPaddingLeft() - + actionView.getPaddingRight() + actionView.getPaddingLeft() + padding * 2; if (totalContentWidth > params.width) { // The text doesn't fit in our standard width so update width to accommodate. @@ -113,17 +138,8 @@ public class Snackbar extends AbstractFloatingView { params.width = maxWidth; } } - labelView.setText(labelText); - actionView.setText(actionText); - actionView.setOnClickListener(v -> { - if (onActionClicked != null) { - onActionClicked.run(); - } - snackbar.mOnDismissed = null; - snackbar.close(true); - }); - snackbar.mOnDismissed = onDismissed; + snackbar.mOnDismissed = onDismissed; snackbar.setAlpha(0); snackbar.setScaleX(0.8f); snackbar.setScaleY(0.8f); From 4e678ff6d5bb6c12ab8e2a76c00600eb61de897d Mon Sep 17 00:00:00 2001 From: Fedor Kudasov Date: Thu, 11 Nov 2021 21:10:03 +0000 Subject: [PATCH 02/11] Separate getTaskViewAt usage getTaskViewAt is used in two different contexts with different assumptions: 1. In the context of iterating over the all TaskViews, where the valid tasks indices are know. 2. In the context of requesting some TaskView by index, where the caller expects null when the input index is invalid. The nullability status of the method differs in these contexts and therefore getTaskViewAt usage can be separated into two different methods. Bug: 205828770 Test: m LauncherGoResLib Change-Id: I42c04c115c309f1849f9dfbb05c74b9b080acf13 (cherry picked from commit 4da3b4bdddbbff7a0dee1f57b3a74c616231e100) --- .../android/quickstep/views/RecentsView.java | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 3aa8d4637b..e270cb7c1c 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -107,6 +107,7 @@ import android.widget.ListView; import android.widget.OverScroller; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.core.graphics.ColorUtils; @@ -181,6 +182,7 @@ import com.android.wm.shell.pip.IPipAnimationListener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; /** @@ -822,7 +824,7 @@ public abstract class RecentsView 0) { - targetPage = indexOfChild(getTaskViewAt(0)); + targetPage = indexOfChild(requireTaskViewAt(0)); } } else if (currentTaskId != -1) { currentTaskView = getTaskViewByTaskId(currentTaskId); @@ -1452,7 +1454,7 @@ public abstract class RecentsView= 0; i--) { - removeView(getTaskViewAt(i)); + removeView(requireTaskViewAt(i)); } if (indexOfChild(mClearAllButton) != -1) { removeView(mClearAllButton); @@ -1498,7 +1500,7 @@ public abstract class RecentsView= 0; i--) { - TaskView taskView = getTaskViewAt(i); + TaskView taskView = requireTaskViewAt(i); if (mIgnoreResetTaskId != taskView.getTaskIds()[0]) { taskView.resetViewTransforms(); taskView.setIconScaleAndDim(mTaskIconScaledDown ? 0 : 1); @@ -1529,7 +1531,7 @@ public abstract class RecentsView 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f; // Pick the next focused task from the preferred row. for (int i = 0; i < taskCount; i++) { - TaskView taskView = getTaskViewAt(i); + TaskView taskView = requireTaskViewAt(i); if (taskView == dismissedTaskView) { continue; } @@ -2816,7 +2818,7 @@ public abstract class RecentsView= 0; i--) { - TaskView child = getTaskViewAt(i); + TaskView child = requireTaskViewAt(i); int[] childTaskIds = child.getTaskIds(); if (!mRunningTaskTileHidden || (childTaskIds[0] != runningTaskId && childTaskIds[1] != runningTaskId)) { @@ -3542,6 +3544,14 @@ public abstract class RecentsView 0) { - final View taskView = getTaskViewAt(0); - getTaskViewAt(count - 1).getHitRect(mTaskViewDeadZoneRect); + final View taskView = requireTaskViewAt(0); + requireTaskViewAt(count - 1).getHitRect(mTaskViewDeadZoneRect); mTaskViewDeadZoneRect.union(taskView.getLeft(), taskView.getTop(), taskView.getRight(), taskView.getBottom()); } @@ -4548,7 +4558,7 @@ public abstract class RecentsView Date: Wed, 23 Jun 2021 15:16:39 -0700 Subject: [PATCH 03/11] [DO NOT MERGE] Make the cutout slightly smaller Temporary fix for S. Leaving the bug open for a proper fix in T. Since we reverted the z order back (launcher on top), we should apply this fix from S and find a proper solution in T Bug: 189265196 Test: https://screenshot.googleplex.com/75fgCva736rqwg5 Change-Id: Ice3b189a41f759e090334e360e44543eabc4836d (cherry picked from commit 26f47c711ad94e4f9f7daef7ea45b35b2e51f53f) --- .../android/quickstep/views/TaskThumbnailView.java | 14 ++++++++++++-- .../src/com/android/quickstep/views/TaskView.java | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index d91669ad96..da92551526 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -19,6 +19,7 @@ package com.android.quickstep.views; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; +import static com.android.launcher3.Utilities.comp; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN; @@ -290,8 +291,17 @@ public class TaskThumbnailView extends View { float cornerRadius) { if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) { - canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint); - canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, + // TODO(b/189265196): Temporary fix to align the surface with the cutout perfectly. + // Round up only when the live tile task is displayed in Overview. + float rounding = comp(mFullscreenParams.mFullscreenProgress); + float left = x + rounding / 2; + float top = y + rounding / 2; + float right = width - rounding; + float bottom = height - rounding; + + canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, + mClearPaint); + canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, mDimmingPaintAfterClearing); return; } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index e8077cf4a5..b122e7c3a2 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -1531,6 +1531,7 @@ public class TaskView extends FrameLayout implements Reusable { private final float mCornerRadius; private final float mWindowCornerRadius; + public float mFullscreenProgress; public RectF mCurrentDrawnInsets = new RectF(); public float mCurrentDrawnCornerRadius; /** The current scale we apply to the thumbnail to adjust for new left/right insets. */ @@ -1548,6 +1549,8 @@ public class TaskView extends FrameLayout implements Reusable { */ public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale, int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) { + mFullscreenProgress = fullscreenProgress; + RectF insets = pph.getInsetsToDrawInFullscreen(dp); float currentInsetsLeft = insets.left * fullscreenProgress; From 8176366f54e713b253426e165c7982544f28c413 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Tue, 30 Nov 2021 17:15:40 +0800 Subject: [PATCH 04/11] Remove stage type from split screen APIs Bug: 198438631 Test: manual check Change-Id: Ic4f41e39013e4d49585da4cda9b28151c549357a --- quickstep/src/com/android/quickstep/SystemUiProxy.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 2543e6c594..5fd66d82eb 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -593,11 +593,11 @@ public class SystemUiProxy implements ISystemUiProxy, } } - public void startShortcut(String packageName, String shortcutId, int stage, int position, + public void startShortcut(String packageName, String shortcutId, int position, Bundle options, UserHandle user) { if (mSplitScreen != null) { try { - mSplitScreen.startShortcut(packageName, shortcutId, stage, position, options, + mSplitScreen.startShortcut(packageName, shortcutId, position, options, user); } catch (RemoteException e) { Log.w(TAG, "Failed call startShortcut"); @@ -605,11 +605,11 @@ public class SystemUiProxy implements ISystemUiProxy, } } - public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position, + public void startIntent(PendingIntent intent, Intent fillInIntent, int position, Bundle options) { if (mSplitScreen != null) { try { - mSplitScreen.startIntent(intent, fillInIntent, stage, position, options); + mSplitScreen.startIntent(intent, fillInIntent, position, options); } catch (RemoteException e) { Log.w(TAG, "Failed call startIntent"); } From 53ae5d85a6cb056ffd191e6b382ebed3e2dd95c2 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Wed, 24 Nov 2021 08:54:25 -0800 Subject: [PATCH 05/11] Tapl Widgets: Don't use container width as gesture margin The test used margin that was equal to the width of the container when injecting a backward swipe. This means the swipe was injected at an x value of 0 in the View's local coordinates. When injecting such events into the system, the coordinates will undergo several transformations, at which point floating point precision errors could accumulate. This could result in the event being dispatched outside the boundary of the view. Change the injection margin so that the swipe is injected in the middle of the View instead of at its edge. Bug: 201777251 Bug: 207146693 Test: atest TaplTestsLauncher3 Change-Id: I4082c2845aef033a6fbe41070061866d6048e21d --- tests/tapl/com/android/launcher3/tapl/Widgets.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java index 6e7264ac0b..0bac2ca258 100644 --- a/tests/tapl/com/android/launcher3/tapl/Widgets.java +++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java @@ -77,7 +77,8 @@ public final class Widgets extends LauncherInstrumentation.VisibleContainer { mLauncher.scroll( widgetsContainer, Direction.UP, - new Rect(0, 0, mLauncher.getVisibleBounds(widgetsContainer).width(), 0), + new Rect(0, 0, mLauncher.getRightGestureMarginInContainer(widgetsContainer) + 1, + 0), FLING_STEPS, false); try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) { verifyActiveContainer(); From f6c28a4381e53fe1f2dbb08d6b4d0f8ed98f4a09 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 30 Nov 2021 14:37:36 -0800 Subject: [PATCH 06/11] Fix potential memory leak by setting mControllers = null Test: N/A Bug: 202511986 Change-Id: Iad7cc89e0e68ce09ebe4ca3ab89392b50b6a82c7 --- .../launcher3/taskbar/FallbackTaskbarUIController.java | 1 + .../launcher3/taskbar/LauncherTaskbarUIController.java | 1 + .../android/launcher3/taskbar/TaskbarUIController.java | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java index 90c035fed0..f1e67479f5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java @@ -60,6 +60,7 @@ public class FallbackTaskbarUIController extends TaskbarUIController { @Override protected void onDestroy() { + super.onDestroy(); mRecentsActivity.setTaskbarUIController(null); mRecentsActivity.getStateManager().removeStateListener(mStateListener); } diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 7d234392c4..2622700871 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -99,6 +99,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override protected void onDestroy() { + super.onDestroy(); onLauncherResumedOrPaused(false); mTaskbarLauncherStateController.onDestroy(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index f713dcabcb..f6bc785a14 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -18,6 +18,8 @@ package com.android.launcher3.taskbar; import android.graphics.Rect; import android.view.View; +import androidx.annotation.CallSuper; + import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.WorkspaceItemInfo; @@ -33,11 +35,15 @@ public class TaskbarUIController { // Initialized in init. protected TaskbarControllers mControllers; + @CallSuper protected void init(TaskbarControllers taskbarControllers) { mControllers = taskbarControllers; } - protected void onDestroy() { } + @CallSuper + protected void onDestroy() { + mControllers = null; + } protected boolean isTaskbarTouchable() { return true; From 570653346f6c2bbde5eeaf650741b1b573f90a8a Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 24 Nov 2021 19:54:07 -0800 Subject: [PATCH 07/11] Add task unpinning support for 3 button taskbar Bug: 199544447 Test: Tested on small and large screen Change-Id: Ib7785992ef11825cd07a929e2cb623d02ef246f1 --- .../taskbar/NavbarButtonsViewController.java | 8 +- .../taskbar/TaskbarActivityContext.java | 1 + .../launcher3/taskbar/TaskbarManager.java | 5 +- .../taskbar/TaskbarNavButtonController.java | 99 +++++++++-- .../TaskbarNavButtonControllerTest.java | 159 ++++++++++++++++++ 5 files changed, 255 insertions(+), 17 deletions(-) create mode 100644 quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 0ab775694a..ce1e8b6b6e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -31,6 +31,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_I 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_QUICK_SETTINGS_EXPANDED; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; @@ -86,6 +87,7 @@ public class NavbarButtonsViewController { private static final int FLAG_DISABLE_RECENTS = 1 << 8; private static final int FLAG_DISABLE_BACK = 1 << 9; private static final int FLAG_NOTIFICATION_SHADE_EXPANDED = 1 << 10; + private static final int FLAG_SCREEN_PINNING_ACTIVE = 1 << 10; private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE; @@ -152,7 +154,9 @@ public class NavbarButtonsViewController { mPropertyHolders.add(new StatePropertyHolder( mControllers.taskbarViewController.getTaskbarIconAlpha() .getProperty(ALPHA_INDEX_KEYGUARD), - flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0, MultiValueAlpha.VALUE, 1, 0)); + flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 + && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0, + MultiValueAlpha.VALUE, 1, 0)); mPropertyHolders.add(new StatePropertyHolder(mControllers.taskbarDragLayerController .getKeyguardBgTaskbar(), @@ -286,6 +290,7 @@ public class NavbarButtonsViewController { int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED; boolean isNotificationShadeExpanded = (sysUiStateFlags & shadeExpandedFlags) != 0; + boolean isScreenPinningActive = (sysUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0; // TODO(b/202218289) we're getting IME as not visible on lockscreen from system updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible); @@ -295,6 +300,7 @@ public class NavbarButtonsViewController { updateStateForFlag(FLAG_DISABLE_RECENTS, isRecentsDisabled); updateStateForFlag(FLAG_DISABLE_BACK, isBackDisabled); updateStateForFlag(FLAG_NOTIFICATION_SHADE_EXPANDED, isNotificationShadeExpanded); + updateStateForFlag(FLAG_SCREEN_PINNING_ACTIVE, isScreenPinningActive); if (mA11yButton != null) { // Only used in 3 button diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index cb9d4a4374..692352b3fd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -361,6 +361,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit); mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags, fromInit); + mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 56e9429120..3cdcdf7f89 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -29,8 +29,8 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.hardware.display.DisplayManager; import android.net.Uri; +import android.os.Handler; import android.provider.Settings; -import android.util.Log; import android.view.Display; import androidx.annotation.NonNull; @@ -93,7 +93,8 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen Display display = service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY); mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null); - mNavButtonController = new TaskbarNavButtonController(service); + mNavButtonController = new TaskbarNavButtonController(service, + SystemUiProxy.INSTANCE.get(mContext), new Handler()); mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar(); mComponentCallbacks = new ComponentCallbacks() { private Configuration mOldConfig = mContext.getResources().getConfiguration(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java index ae23eda2a4..d23336505a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java @@ -19,8 +19,10 @@ package com.android.launcher3.taskbar; import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS; import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; import android.os.Bundle; +import android.os.Handler; import androidx.annotation.IntDef; @@ -40,6 +42,13 @@ import java.lang.annotation.RetentionPolicy; */ public class TaskbarNavButtonController { + /** Allow some time in between the long press for back and recents. */ + static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200; + static final int SCREEN_PIN_LONG_PRESS_RESET = SCREEN_PIN_LONG_PRESS_THRESHOLD + 100; + + private long mLastScreenPinLongPress; + private boolean mScreenPinned; + @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BUTTON_BACK, @@ -57,10 +66,20 @@ public class TaskbarNavButtonController { static final int BUTTON_IME_SWITCH = BUTTON_RECENTS << 1; static final int BUTTON_A11Y = BUTTON_IME_SWITCH << 1; - private final TouchInteractionService mService; + private static final int SCREEN_UNPIN_COMBO = BUTTON_BACK | BUTTON_RECENTS; + private int mLongPressedButtons = 0; - public TaskbarNavButtonController(TouchInteractionService service) { + private final TouchInteractionService mService; + private final SystemUiProxy mSystemUiProxy; + private final Handler mHandler; + + private final Runnable mResetLongPress = this::resetScreenUnpin; + + public TaskbarNavButtonController(TouchInteractionService service, + SystemUiProxy systemUiProxy, Handler handler) { mService = service; + mSystemUiProxy = systemUiProxy; + mHandler = handler; } public void onButtonClick(@TaskbarButton int buttonType) { @@ -72,13 +91,13 @@ public class TaskbarNavButtonController { navigateHome(); break; case BUTTON_RECENTS: - navigateToOverview();; + navigateToOverview(); break; case BUTTON_IME_SWITCH: showIMESwitcher(); break; case BUTTON_A11Y: - notifyImeClick(false /* longClick */); + notifyA11yClick(false /* longClick */); break; } } @@ -89,46 +108,98 @@ public class TaskbarNavButtonController { startAssistant(); return true; case BUTTON_A11Y: - notifyImeClick(true /* longClick */); + notifyA11yClick(true /* longClick */); return true; case BUTTON_BACK: - case BUTTON_IME_SWITCH: case BUTTON_RECENTS: + mLongPressedButtons |= buttonType; + return determineScreenUnpin(); + case BUTTON_IME_SWITCH: default: return false; } } + /** + * Checks if the user has long pressed back and recents buttons + * "together" (within {@link #SCREEN_PIN_LONG_PRESS_THRESHOLD})ms + * If so, then requests the system to turn off screen pinning. + * + * @return true if the long press is a valid user action in attempting to unpin an app + * Will always return {@code false} when screen pinning is not active. + * NOTE: Returning true does not mean that screen pinning has stopped + */ + private boolean determineScreenUnpin() { + long timeNow = System.currentTimeMillis(); + if (!mScreenPinned) { + return false; + } + + if (mLastScreenPinLongPress == 0) { + // First button long press registered, just mark time and wait for second button press + mLastScreenPinLongPress = System.currentTimeMillis(); + mHandler.postDelayed(mResetLongPress, SCREEN_PIN_LONG_PRESS_RESET); + return true; + } + + if ((timeNow - mLastScreenPinLongPress) > SCREEN_PIN_LONG_PRESS_THRESHOLD) { + // Too long in-between presses, reset the clock + resetScreenUnpin(); + return false; + } + + if ((mLongPressedButtons & SCREEN_UNPIN_COMBO) == SCREEN_UNPIN_COMBO) { + // Hooray! They did it (finally...) + mSystemUiProxy.stopScreenPinning(); + mHandler.removeCallbacks(mResetLongPress); + resetScreenUnpin(); + } + return true; + } + + private void resetScreenUnpin() { + mLongPressedButtons = 0; + mLastScreenPinLongPress = 0; + } + + public void updateSysuiFlags(int sysuiFlags) { + mScreenPinned = (sysuiFlags & SYSUI_STATE_SCREEN_PINNING) != 0; + } + private void navigateHome() { mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME); } private void navigateToOverview() { + if (mScreenPinned) { + return; + } TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle"); mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_TOGGLE); } private void executeBack() { - SystemUiProxy.INSTANCE.getNoCreate().onBackPressed(); + mSystemUiProxy.onBackPressed(); } private void showIMESwitcher() { - SystemUiProxy.INSTANCE.getNoCreate().onImeSwitcherPressed(); + mSystemUiProxy.onImeSwitcherPressed(); } - private void notifyImeClick(boolean longClick) { - SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate(); + private void notifyA11yClick(boolean longClick) { if (longClick) { - systemUiProxy.notifyAccessibilityButtonLongClicked(); + mSystemUiProxy.notifyAccessibilityButtonLongClicked(); } else { - systemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId()); + mSystemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId()); } } private void startAssistant() { + if (mScreenPinned) { + return; + } Bundle args = new Bundle(); args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS); - SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate(); - systemUiProxy.startAssistant(args); + mSystemUiProxy.startAssistant(args); } } diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java new file mode 100644 index 0000000000..ba1a60dd38 --- /dev/null +++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java @@ -0,0 +1,159 @@ +package com.android.launcher3.taskbar; + +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.SCREEN_PIN_LONG_PRESS_THRESHOLD; +import static com.android.quickstep.OverviewCommandHelper.TYPE_HOME; +import static com.android.quickstep.OverviewCommandHelper.TYPE_TOGGLE; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.os.Handler; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.quickstep.OverviewCommandHelper; +import com.android.quickstep.SystemUiProxy; +import com.android.quickstep.TouchInteractionService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class TaskbarNavButtonControllerTest { + + private final static int DISPLAY_ID = 2; + + @Mock + SystemUiProxy mockSystemUiProxy; + @Mock + TouchInteractionService mockService; + @Mock + OverviewCommandHelper mockCommandHelper; + @Mock + Handler mockHandler; + + private TaskbarNavButtonController mNavButtonController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(mockService.getDisplayId()).thenReturn(DISPLAY_ID); + when(mockService.getOverviewCommandHelper()).thenReturn(mockCommandHelper); + mNavButtonController = new TaskbarNavButtonController(mockService, + mockSystemUiProxy, mockHandler); + } + + @Test + public void testPressBack() { + mNavButtonController.onButtonClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(1)).onBackPressed(); + } + + @Test + public void testPressImeSwitcher() { + mNavButtonController.onButtonClick(BUTTON_IME_SWITCH); + verify(mockSystemUiProxy, times(1)).onImeSwitcherPressed(); + } + + @Test + public void testPressA11yShortClick() { + mNavButtonController.onButtonClick(BUTTON_A11Y); + verify(mockSystemUiProxy, times(1)) + .notifyAccessibilityButtonClicked(DISPLAY_ID); + } + + @Test + public void testPressA11yLongClick() { + mNavButtonController.onButtonLongClick(BUTTON_A11Y); + verify(mockSystemUiProxy, times(1)).notifyAccessibilityButtonLongClicked(); + } + + @Test + public void testLongPressHome() { + mNavButtonController.onButtonLongClick(BUTTON_HOME); + verify(mockSystemUiProxy, times(1)).startAssistant(any()); + } + + @Test + public void testPressHome() { + mNavButtonController.onButtonClick(BUTTON_HOME); + verify(mockCommandHelper, times(1)).addCommand(TYPE_HOME); + } + + @Test + public void testPressRecents() { + mNavButtonController.onButtonClick(BUTTON_RECENTS); + verify(mockCommandHelper, times(1)).addCommand(TYPE_TOGGLE); + } + + @Test + public void testPressRecentsWithScreenPinned() { + mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING); + mNavButtonController.onButtonClick(BUTTON_RECENTS); + verify(mockCommandHelper, times(0)).addCommand(TYPE_TOGGLE); + } + + @Test + public void testLongPressBackRecentsNotPinned() { + mNavButtonController.onButtonLongClick(BUTTON_RECENTS); + mNavButtonController.onButtonLongClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(0)).stopScreenPinning(); + } + + @Test + public void testLongPressBackRecentsPinned() { + mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING); + mNavButtonController.onButtonLongClick(BUTTON_RECENTS); + mNavButtonController.onButtonLongClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(1)).stopScreenPinning(); + } + + @Test + public void testLongPressBackRecentsTooLongPinned() { + mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING); + mNavButtonController.onButtonLongClick(BUTTON_RECENTS); + try { + Thread.sleep(SCREEN_PIN_LONG_PRESS_THRESHOLD + 5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mNavButtonController.onButtonLongClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(0)).stopScreenPinning(); + } + + @Test + public void testLongPressBackRecentsMultipleAttemptPinned() { + mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING); + mNavButtonController.onButtonLongClick(BUTTON_RECENTS); + try { + Thread.sleep(SCREEN_PIN_LONG_PRESS_THRESHOLD + 5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mNavButtonController.onButtonLongClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(0)).stopScreenPinning(); + + // Try again w/in threshold + mNavButtonController.onButtonLongClick(BUTTON_RECENTS); + mNavButtonController.onButtonLongClick(BUTTON_BACK); + verify(mockSystemUiProxy, times(1)).stopScreenPinning(); + } + + @Test + public void testLongPressHomeScreenPinned() { + mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING); + mNavButtonController.onButtonLongClick(BUTTON_HOME); + verify(mockSystemUiProxy, times(0)).startAssistant(any()); + } +} From b997930afcec95289c845030eb5c381cc99b4190 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Tue, 30 Nov 2021 19:58:00 -0800 Subject: [PATCH 08/11] Treat RTL split placeholder animation same as LTR * Since we're doing all transformations in screen coordinates we don't need to account for RTL. Bug: 202156862 Change-Id: Ibcbf698dbc5b8fabf2647949de6d2718937832d5 --- .../android/quickstep/views/FloatingTaskView.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 325ec044fe..a343e0a593 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -129,9 +129,7 @@ public class FloatingTaskView extends FrameLayout { public void update(RectF position, float progress, float windowRadius) { MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); - float dX = mIsRtl - ? position.left - (lp.getMarginStart() - lp.width) - : position.left - lp.getMarginStart(); + float dX = position.left - lp.getMarginStart(); float dY = position.top - lp.topMargin; setTranslationX(dX); @@ -157,16 +155,10 @@ public class FloatingTaskView extends FrameLayout { lp.ignoreInsets = true; // Position the floating view exactly on top of the original lp.topMargin = Math.round(pos.top); - if (mIsRtl) { - lp.setMarginStart(Math.round(mLauncher.getDeviceProfile().widthPx - pos.right)); - } else { - lp.setMarginStart(Math.round(pos.left)); - } + lp.setMarginStart(Math.round(pos.left)); // Set the properties here already to make sure they are available when running the first // animation frame. - int left = mIsRtl - ? mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width - : lp.leftMargin; + int left = lp.leftMargin; layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height); } From 09a822a6fe32a53cb4378177f920f31a051f89b6 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Fri, 26 Nov 2021 11:44:05 -0800 Subject: [PATCH 09/11] Schedule OverviewCommandHelper callbacks for GroupedTaskView * Schedule runnables to clear pending queue in OverviewCommandHelper similar to how TaskView does it. * End callbacks get run when recents animation finishes in RecentsView in the case of live tile when recents animation is still running OR in directly when the split remote animation finishes Bug: 207845542 Change-Id: I7e858ce55b08cde6436d44f2e857e28b73458f0b --- .../android/quickstep/views/GroupedTaskView.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 00f541d4c6..b43626b50e 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -157,10 +157,20 @@ public class GroupedTaskView extends TaskView { @Nullable @Override public RunnableList launchTaskAnimated() { - getRecentsView().getSplitPlaceholder().launchTasks(this /*groupedTaskView*/, - null /*callback*/, + if (mTask == null || mSecondaryTask == null) { + return null; + } + + RunnableList endCallback = new RunnableList(); + RecentsView recentsView = getRecentsView(); + // Callbacks run from remote animation when recents animation not currently running + recentsView.getSplitPlaceholder().launchTasks(this /*groupedTaskView*/, + success -> endCallback.executeAllAndDestroy(), false /* freezeTaskList */); - return null; + + // Callbacks get run from recentsView for case when recents animation already running + recentsView.addSideTaskLaunchCallback(endCallback); + return endCallback; } @Override From a30749252542988e0dc1d11ddc2cbbf85bc2c32e Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 1 Dec 2021 15:52:32 +0000 Subject: [PATCH 10/11] Removed onBackPressed handling in SplitSCreenSelectState - So it'll have exact same behavior as OverviewState to exit overview when going back - Also removed RecentsView.cancelSplitSelect as it's longer needed Fix: 181707736 Test: manual Change-Id: Ide4dfc64680ecc9adfe245ae2de1463735b0490e --- .../RecentsViewStateController.java | 1 - .../states/SplitScreenSelectState.java | 5 - .../android/quickstep/views/RecentsView.java | 106 ------------------ 3 files changed, 112 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index b21d677106..771657b11d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -92,7 +92,6 @@ public final class RecentsViewStateController extends builder.add(mRecentsView.createSplitSelectInitAnimation().buildAnim()); mRecentsView.applySplitPrimaryScrollOffset(); } else if (!isSplitSelectionState(toState) && isSplitSelectionState(currentState)) { - builder.add(mRecentsView.cancelSplitSelect(true).buildAnim()); mRecentsView.resetSplitPrimaryScrollOffset(); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java index 106375a765..4f5f27a2c0 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java @@ -30,11 +30,6 @@ public class SplitScreenSelectState extends OverviewState { super(id); } - @Override - public void onBackPressed(Launcher launcher) { - launcher.getStateManager().goToState(OVERVIEW); - } - @Override public int getVisibleElements(Launcher launcher) { return SPLIT_PLACHOLDER_VIEW; diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 9cf76b378a..3020dd905d 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1123,9 +1123,6 @@ public abstract class RecentsView view.getVisibility() != GONE && view != mSplitHiddenTaskView); - - int[] newScroll = new int[getChildCount()]; - getPageScrolls(newScroll, false, SIMPLE_SCROLL_LOGIC); - - boolean needsCurveUpdates = false; - for (int i = mSplitHiddenTaskViewIndex; i >= 0; i--) { - View child = getChildAt(i); - if (child == mSplitHiddenTaskView) { - TaskView taskView = (TaskView) child; - - int dir = mOrientationHandler.getSplitTaskViewDismissDirection(stagePosition, - mActivity.getDeviceProfile()); - FloatProperty dismissingTaskViewTranslate; - Rect hiddenBounds = new Rect(taskView.getLeft(), taskView.getTop(), - taskView.getRight(), taskView.getBottom()); - int distanceDelta = 0; - if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE) { - dismissingTaskViewTranslate = taskView - .getSecondaryDissmissTranslationProperty(); - distanceDelta = initialBounds.top - hiddenBounds.top; - taskView.layout(initialBounds.left, hiddenBounds.top, initialBounds.right, - hiddenBounds.bottom); - } else { - dismissingTaskViewTranslate = taskView - .getPrimaryDismissTranslationProperty(); - distanceDelta = initialBounds.left - hiddenBounds.left; - taskView.layout(hiddenBounds.left, initialBounds.top, hiddenBounds.right, - initialBounds.bottom); - if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE) { - distanceDelta *= -1; - } - } - pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, - dismissingTaskViewTranslate, - distanceDelta)); - pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, ALPHA, 1)); - } else { - // If insertion is on last index (furthest from clear all), we directly add the view - // else we translate all views to the right of insertion index further right, - // ignore views to left - if (showAsGrid()) { - // TODO(b/186800707) handle more elegantly for grid - continue; - } - int scrollDiff = newScroll[i] - oldScroll[i]; - if (scrollDiff != 0) { - FloatProperty translationProperty = child instanceof TaskView - ? ((TaskView) child).getPrimaryDismissTranslationProperty() - : mOrientationHandler.getPrimaryViewTranslate(); - - ResourceProvider rp = DynamicResource.provider(mActivity); - SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_END) - .setDampingRatio( - rp.getFloat(R.dimen.dismiss_task_trans_x_damping_ratio)) - .setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_x_stiffness)); - pendingAnim.add(ObjectAnimator.ofFloat(child, translationProperty, scrollDiff) - .setDuration(duration), ACCEL, sp); - needsCurveUpdates = true; - } - } - } - - if (needsCurveUpdates) { - pendingAnim.addOnFrameCallback(this::updateCurveProperties); - } - - pendingAnim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // TODO(b/186800707) Figure out how to undo for grid view - // Need to handle cases where dismissed task is - // * Top Row - // * Bottom Row - // * Focused Task - updateGridProperties(); - resetFromSplitSelectionState(); - updateScrollSynchronously(); - } - }); - - return pendingAnim; - } - /** TODO(b/181707736) More gracefully handle exiting split selection state */ private void resetFromSplitSelectionState() { if (!mActivity.getDeviceProfile().overviewShowAsGrid) { From 4536c2fc303847fdc29a39837e069f0d01a26afa Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 1 Dec 2021 17:23:46 +0000 Subject: [PATCH 11/11] Apply/reset split scroll offset regardless of previous state - Also do the same in setState without animation Fix: 208605204 Test: Exit split screen and enter overview Change-Id: I34dd102527dffa90925b6f0fd22465f1fe6e819c --- .../uioverrides/RecentsViewStateController.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 771657b11d..19897a1bf8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -66,6 +66,12 @@ public final class RecentsViewStateController extends // In Overview, we may be layering app surfaces behind Launcher, so we need to notify // DepthController to prevent optimizations which might occlude the layers behind mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi); + + if (isSplitSelectionState(state)) { + mRecentsView.applySplitPrimaryScrollOffset(); + } else { + mRecentsView.resetSplitPrimaryScrollOffset(); + } } @Override @@ -90,8 +96,10 @@ public final class RecentsViewStateController extends LauncherState currentState = mLauncher.getStateManager().getState(); if (isSplitSelectionState(toState) && !isSplitSelectionState(currentState)) { builder.add(mRecentsView.createSplitSelectInitAnimation().buildAnim()); + } + if (isSplitSelectionState(toState)) { mRecentsView.applySplitPrimaryScrollOffset(); - } else if (!isSplitSelectionState(toState) && isSplitSelectionState(currentState)) { + } else { mRecentsView.resetSplitPrimaryScrollOffset(); }