diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 9db03f53a6..7e0530bcc0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -673,18 +673,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mIsFullscreen; } - /** - * Notify system to inset the rounded corner frame based on the task bar insets. - */ - public void updateInsetRoundedCornerFrame(boolean shouldInsetsRoundedCorner) { - if (!mDragLayer.isAttachedToWindow() - || mWindowLayoutParams.insetsRoundedCornerFrame == shouldInsetsRoundedCorner) { - return; - } - mWindowLayoutParams.insetsRoundedCornerFrame = shouldInsetsRoundedCorner; - mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); - } - /** * Updates the TaskbarContainer height (pass {@link #getDefaultTaskbarWindowHeight()} to reset). */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index c029097b71..19b9a1868e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -71,7 +71,6 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas fun init(controllers: TaskbarControllers) { this.controllers = controllers windowLayoutParams = context.windowLayoutParams - windowLayoutParams.insetsRoundedCornerFrame = true onTaskbarWindowHeightOrInsetsChanged() context.addOnDeviceProfileChangeListener(deviceProfileChangeListener) @@ -86,23 +85,23 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas fun onTaskbarWindowHeightOrInsetsChanged() { if (context.isGestureNav) { windowLayoutParams.providedInsets = - arrayOf( - InsetsFrameProvider(insetsOwner, 0, navigationBars()) - .setFlags(FLAG_SUPPRESS_SCRIM, FLAG_SUPPRESS_SCRIM), - InsetsFrameProvider(insetsOwner, 0, tappableElement()), - InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()), - InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures()) - .setSource(SOURCE_DISPLAY), - InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures()) - .setSource(SOURCE_DISPLAY) - ) + arrayOf( + InsetsFrameProvider(insetsOwner, 0, navigationBars()) + .setFlags(FLAG_SUPPRESS_SCRIM, FLAG_SUPPRESS_SCRIM), + InsetsFrameProvider(insetsOwner, 0, tappableElement()), + InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()), + InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures()) + .setSource(SOURCE_DISPLAY), + InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures()) + .setSource(SOURCE_DISPLAY) + ) } else { windowLayoutParams.providedInsets = - arrayOf( - InsetsFrameProvider(insetsOwner, 0, navigationBars()), - InsetsFrameProvider(insetsOwner, 0, tappableElement()), - InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()) - ) + arrayOf( + InsetsFrameProvider(insetsOwner, 0, navigationBars()), + InsetsFrameProvider(insetsOwner, 0, tappableElement()), + InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()) + ) } val touchableHeight = controllers.taskbarStashController.touchableHeight @@ -162,6 +161,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas provider.insetsSizeOverrides = insetsSizeOverride } } + + // We only report tappableElement height for unstashed, persistent taskbar, + // which is also when we draw the rounded corners above taskbar. + windowLayoutParams.insetsRoundedCornerFrame = tappableHeight > 0 + context.notifyUpdateLayoutParams() } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index e334d0569d..b2f93787e0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -106,9 +106,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO; - private static final int FLAGS_STASHED_IN_APP_IGNORING_IME = - FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME; - // If any of these flags are enabled, inset apps by our stashed height instead of our unstashed // height. This way the reported insets are consistent even during transitions out of the app. // Currently any flag that causes us to stash in an app is included, except for IME or All Apps @@ -413,13 +410,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return hasAnyFlag(FLAGS_STASHED_IN_APP); } - /** - * Returns whether the taskbar should be stashed in apps regardless of the IME visibility. - */ - public boolean isStashedInAppIgnoringIme() { - return hasAnyFlag(FLAGS_STASHED_IN_APP_IGNORING_IME); - } - /** * Returns whether the taskbar should be stashed in the current LauncherState. */ @@ -1059,11 +1049,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private void notifyStashChange(boolean visible, boolean stashed) { mSystemUiProxy.notifyTaskbarStatus(visible, stashed); setUpTaskbarSystemAction(visible); - // If stashing taskbar is caused by IME visibility, we could just skip updating rounded - // corner insets since the rounded corners will be covered by IME during IME is showing and - // taskbar will be restored back to unstashed when IME is hidden. - mControllers.taskbarActivityContext.updateInsetRoundedCornerFrame( - visible && !isStashedInAppIgnoringIme()); mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java index 36e78fba80..39543b0d7d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java @@ -95,7 +95,11 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { i -> MAIN_EXECUTOR.execute(() -> sHolders.forEach(h -> h.mAppWidgetRemovedCallback.accept(i))), () -> MAIN_EXECUTOR.execute(() -> - sHolders.forEach(h -> h.mProviderChangedListeners.forEach( + sHolders.forEach(h -> + // Listeners might remove themselves from the list during the + // iteration. Creating a copy of the list to avoid exceptions + // for concurrent modification. + new ArrayList<>(h.mProviderChangedListeners).forEach( ProviderChangedListener::notifyWidgetProvidersChanged))), UI_HELPER_EXECUTOR.getLooper()); if (!WidgetsModel.GO_DISABLE_WIDGETS) { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index b7a29e0034..5333cbe919 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -177,7 +177,7 @@ public abstract class AbsSwipeUpHandler, protected @Nullable RecentsAnimationController mDeferredCleanupRecentsAnimationController; protected RecentsAnimationTargets mRecentsAnimationTargets; protected T mActivity; - protected Q mRecentsView; + protected @Nullable Q mRecentsView; protected Runnable mGestureEndCallback; protected MultiStateCallback mStateCallback; protected boolean mCanceled; @@ -1895,7 +1895,9 @@ public abstract class AbsSwipeUpHandler, private void invalidateHandlerWithLauncher() { endLauncherTransitionController(); - mRecentsView.onGestureAnimationEnd(); + if (mRecentsView != null) { + mRecentsView.onGestureAnimationEnd(); + } resetLauncherListeners(); } @@ -1922,7 +1924,9 @@ public abstract class AbsSwipeUpHandler, private void resetLauncherListeners() { mActivity.getRootView().setOnApplyWindowInsetsListener(null); - mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener); + if (mRecentsView != null) { + mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener); + } } private void resetStateForAnimationCancel() { @@ -1981,8 +1985,10 @@ public abstract class AbsSwipeUpHandler, private boolean updateThumbnail(int runningTaskId, boolean refreshView) { boolean finishTransitionPosted = false; final TaskView taskView; - if (mGestureState.getEndTarget() == HOME || mGestureState.getEndTarget() == NEW_TASK - || mGestureState.getEndTarget() == ALL_APPS) { + if (mGestureState.getEndTarget() == HOME + || mGestureState.getEndTarget() == NEW_TASK + || mGestureState.getEndTarget() == ALL_APPS + || mRecentsView == null) { // Capture the screenshot before finishing the transition to home or quickswitching to // ensure it's taken in the correct orientation, but no need to update the thumbnail. taskView = null; @@ -2135,7 +2141,7 @@ public abstract class AbsSwipeUpHandler, protected void startNewTask(Consumer resultCallback) { // Launch the task user scrolled to (mRecentsView.getNextPage()). if (!mCanceled) { - TaskView nextTask = mRecentsView.getNextPageTaskView(); + TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); if (nextTask != null) { Task.TaskKey nextTaskKey = nextTask.getTask().key; int taskId = nextTaskKey.id; @@ -2237,7 +2243,8 @@ public abstract class AbsSwipeUpHandler, return; } RemoteAnimationTarget taskTarget = taskTargetOptional.get(); - TaskView taskView = mRecentsView.getTaskViewByTaskId(taskTarget.taskId); + TaskView taskView = mRecentsView == null + ? null : mRecentsView.getTaskViewByTaskId(taskTarget.taskId); if (taskView == null || !taskView.getThumbnail().shouldShowSplashView()) { finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */); return; @@ -2296,9 +2303,11 @@ public abstract class AbsSwipeUpHandler, * resume if we finish the controller. */ protected int getLastAppearedTaskIndex() { - return mGestureState.getLastAppearedTaskId() != -1 - ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId()) - : mRecentsView.getRunningTaskIndex(); + return mRecentsView == null + ? -1 + : mGestureState.getLastAppearedTaskId() != -1 + ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId()) + : mRecentsView.getRunningTaskIndex(); } /** diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index 4e892e2722..ab3ae9f1dc 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -149,6 +149,11 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { case TestProtocol.REQUEST_DISABLE_TRANSIENT_TASKBAR: enableTransientTaskbar(false); return response; + + case TestProtocol.REQUEST_SHELL_DRAG_READY: + response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, + SystemUiProxy.INSTANCE.get(mContext).isDragAndDropReady()); + return response; } return super.call(method, arg, extras); diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 616ddef748..89f06f6895 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -70,6 +70,7 @@ import com.android.systemui.unfold.progress.IUnfoldAnimation; import com.android.systemui.unfold.progress.IUnfoldTransitionListener; import com.android.wm.shell.back.IBackAnimation; import com.android.wm.shell.desktopmode.IDesktopMode; +import com.android.wm.shell.draganddrop.IDragAndDrop; import com.android.wm.shell.onehanded.IOneHanded; import com.android.wm.shell.pip.IPip; import com.android.wm.shell.pip.IPipAnimationListener; @@ -128,6 +129,7 @@ public class SystemUiProxy implements ISystemUiProxy { private IBinder mOriginalTransactionToken = null; private IOnBackInvokedCallback mBackToLauncherCallback; private IRemoteAnimationRunner mBackToLauncherRunner; + private IDragAndDrop mDragAndDrop; // Used to dedupe calls to SystemUI private int mLastShelfHeight; @@ -203,7 +205,7 @@ public class SystemUiProxy implements ISystemUiProxy { IStartingWindow startingWindow, IRecentTasks recentTasks, ISysuiUnlockAnimationController sysuiUnlockAnimationController, IBackAnimation backAnimation, IDesktopMode desktopMode, - IUnfoldAnimation unfoldAnimation) { + IUnfoldAnimation unfoldAnimation, IDragAndDrop dragAndDrop) { unlinkToDeath(); mSystemUiProxy = proxy; mPip = pip; @@ -216,6 +218,7 @@ public class SystemUiProxy implements ISystemUiProxy { mBackAnimation = backAnimation; mDesktopMode = desktopMode; mUnfoldAnimation = unfoldAnimation; + mDragAndDrop = dragAndDrop; linkToDeath(); // re-attach the listeners once missing due to setProxy has not been initialized yet. setPipAnimationListener(mPipAnimationListener); @@ -230,7 +233,7 @@ public class SystemUiProxy implements ISystemUiProxy { } public void clearProxy() { - setProxy(null, null, null, null, null, null, null, null, null, null, null); + setProxy(null, null, null, null, null, null, null, null, null, null, null, null); } // TODO(141886704): Find a way to remove this @@ -1099,6 +1102,11 @@ public class SystemUiProxy implements ISystemUiProxy { Log.e(TAG, "Failed call setUnfoldAnimationListener", e); } } + + // + // Recents + // + /** * Starts the recents activity. The caller should manage the thread on which this is called. */ @@ -1131,10 +1139,30 @@ public class SystemUiProxy implements ISystemUiProxy { try { mRecentTasks.startRecentsTransition(mRecentsPendingIntent, intent, optsBundle, mContext.getIApplicationThread(), runner); + return true; } catch (RemoteException e) { Log.e(TAG, "Error starting recents via shell", e); return false; } - return true; + } + + // + // Drag and drop + // + + /** + * For testing purposes. Returns `true` only if the shell drop target has shown and + * drawn and is ready to handle drag events and the subsequent drop. + */ + public boolean isDragAndDropReady() { + if (mDragAndDrop == null) { + return false; + } + try { + return mDragAndDrop.isReadyToHandleDrag(); + } catch (RemoteException e) { + Log.e(TAG, "Error querying drag state", e); + return false; + } } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 038c6743dd..6ea171e6e2 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -43,6 +43,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE; +import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; @@ -125,6 +126,7 @@ import com.android.systemui.shared.tracing.ProtoTraceable; import com.android.systemui.unfold.progress.IUnfoldAnimation; import com.android.wm.shell.back.IBackAnimation; import com.android.wm.shell.desktopmode.IDesktopMode; +import com.android.wm.shell.draganddrop.IDragAndDrop; import com.android.wm.shell.onehanded.IOneHanded; import com.android.wm.shell.pip.IPip; import com.android.wm.shell.recents.IRecentTasks; @@ -185,11 +187,13 @@ public class TouchInteractionService extends Service bundle.getBinder(KEY_EXTRA_SHELL_DESKTOP_MODE)); IUnfoldAnimation unfoldTransition = IUnfoldAnimation.Stub.asInterface( bundle.getBinder(KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER)); + IDragAndDrop dragAndDrop = IDragAndDrop.Stub.asInterface( + bundle.getBinder(KEY_EXTRA_SHELL_DRAG_AND_DROP)); MAIN_EXECUTOR.execute(() -> { SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip, splitscreen, onehanded, shellTransitions, startingWindow, recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode, - unfoldTransition); + unfoldTransition, dragAndDrop); TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()"); preloadOverview(true /* fromInit */); }); diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java index 36255b4628..b472cdbea3 100644 --- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java +++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java @@ -111,6 +111,7 @@ public final class TestProtocol { public static final String REQUEST_IS_TABLET = "is-tablet"; public static final String REQUEST_IS_TWO_PANELS = "is-two-panel"; public static final String REQUEST_START_DRAG_THRESHOLD = "start-drag-threshold"; + public static final String REQUEST_SHELL_DRAG_READY = "shell-drag-ready"; public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT = "get-activities-created-count"; public static final String REQUEST_GET_ACTIVITIES = "get-activities"; diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java index 4a3507ed69..58d5a36d66 100644 --- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java +++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java @@ -16,11 +16,14 @@ package com.android.launcher3.tapl; +import static com.android.launcher3.tapl.LauncherInstrumentation.DEFAULT_POLL_INTERVAL; import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID; +import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS; import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT; import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING; import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT; import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING; +import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_SHELL_DRAG_READY; import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT; import android.graphics.Point; @@ -146,6 +149,12 @@ public final class LaunchedAppState extends Background { try (LauncherInstrumentation.Closable c2 = launcher.addContextLayer( "started item drag")) { + launcher.assertTrue("Shell drag not marked as ready", launcher.waitAndGet(() -> { + LauncherInstrumentation.log("Checking shell drag ready"); + return launcher.getTestInfo(REQUEST_SHELL_DRAG_READY) + .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, false); + }, WAIT_TIME_MS, DEFAULT_POLL_INTERVAL)); + launcher.movePointer( dragStart, endPoint,