diff options
Diffstat (limited to 'libs')
60 files changed, 727 insertions, 475 deletions
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index 563fb4d88941..87a7c3edf826 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -228,9 +228,10 @@ the screen. This time the double-tap can happen on the top or bottom of the screen. To teach the user about this feature, we display an education explaining how the double-tap works and how the app can be moved on the screen. - This is the text we show to the user below an animated icon visualizing the double-tap - action. [CHAR LIMIT=NONE] --> - <string name="letterbox_reachability_reposition_text">Double-tap to move this app</string> + This is the text we show to the user below an icon visualizing the double-tap + action. The description should be split in two lines separated by "\n" like for this + locale. [CHAR LIMIT=NONE] --> + <string name="letterbox_reachability_reposition_text">Double-tap to\nmove this app</string> <!-- Freeform window caption strings --> <!-- Accessibility text for the maximize window button [CHAR LIMIT=NONE] --> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java index 3d1ed87f1305..14daae03e6b5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java @@ -157,14 +157,21 @@ public abstract class TvPipModule { @WMSingleton @Provides static PipTransitionController provideTvPipTransition( + Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Transitions transitions, - PipAnimationController pipAnimationController, + TvPipBoundsState tvPipBoundsState, + PipDisplayLayoutState pipDisplayLayoutState, + PipTransitionState pipTransitionState, + TvPipMenuController pipMenuController, TvPipBoundsAlgorithm tvPipBoundsAlgorithm, - TvPipBoundsState tvPipBoundsState, TvPipMenuController pipMenuController) { - return new TvPipTransition(shellInit, shellTaskOrganizer, transitions, tvPipBoundsState, - pipMenuController, tvPipBoundsAlgorithm, pipAnimationController); + PipAnimationController pipAnimationController, + PipSurfaceTransactionHelper pipSurfaceTransactionHelper) { + return new TvPipTransition(context, shellInit, shellTaskOrganizer, transitions, + tvPipBoundsState, pipDisplayLayoutState, pipTransitionState, pipMenuController, + tvPipBoundsAlgorithm, pipAnimationController, pipSurfaceTransactionHelper, + Optional.empty()); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index e2cd7a0d1d77..d8e2f5c4a817 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -54,6 +54,7 @@ import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler; +import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.freeform.FreeformTaskListener; @@ -677,13 +678,15 @@ public abstract class WMShellModule { SyncTransactionQueue syncQueue, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, Transitions transitions, - EnterDesktopTaskTransitionHandler transitionHandler, + EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, + ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, @ShellMainThread ShellExecutor mainExecutor ) { return new DesktopTasksController(context, shellInit, shellController, displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, transitions, - transitionHandler, desktopModeTaskRepository, mainExecutor); + enterDesktopTransitionHandler, exitDesktopTransitionHandler, + desktopModeTaskRepository, mainExecutor); } @WMSingleton @@ -695,6 +698,15 @@ public abstract class WMShellModule { @WMSingleton @Provides + static ExitDesktopTaskTransitionHandler provideExitDesktopTaskTransitionHandler( + Transitions transitions, + Context context + ) { + return new ExitDesktopTaskTransitionHandler(transitions, context); + } + + @WMSingleton + @Provides @DynamicOverride static DesktopModeTaskRepository provideDesktopModeTaskRepository() { return new DesktopModeTaskRepository(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index cb04a43e7205..c35cd5a8be02 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -68,7 +68,8 @@ class DesktopTasksController( private val syncQueue: SyncTransactionQueue, private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, private val transitions: Transitions, - private val animationTransitionHandler: EnterDesktopTaskTransitionHandler, + private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, + private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, private val desktopModeTaskRepository: DesktopModeTaskRepository, @ShellMainThread private val mainExecutor: ShellExecutor ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler { @@ -149,7 +150,7 @@ class DesktopTasksController( wct.setBounds(taskInfo.token, startBounds) if (Transitions.ENABLE_SHELL_TRANSITIONS) { - animationTransitionHandler.startTransition( + enterDesktopTaskTransitionHandler.startTransition( Transitions.TRANSIT_ENTER_FREEFORM, wct) } else { shellTaskOrganizer.applyTransaction(wct) @@ -167,7 +168,8 @@ class DesktopTasksController( wct.setBounds(taskInfo.token, freeformBounds) if (Transitions.ENABLE_SHELL_TRANSITIONS) { - animationTransitionHandler.startTransition(Transitions.TRANSIT_ENTER_DESKTOP_MODE, wct) + enterDesktopTaskTransitionHandler.startTransition( + Transitions.TRANSIT_ENTER_DESKTOP_MODE, wct) } else { shellTaskOrganizer.applyTransaction(wct) } @@ -191,6 +193,18 @@ class DesktopTasksController( } } + fun moveToFullscreenWithAnimation(task: ActivityManager.RunningTaskInfo) { + val wct = WindowContainerTransaction() + addMoveToFullscreenChanges(wct, task.token) + + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + exitDesktopTaskTransitionHandler.startTransition( + Transitions.TRANSIT_EXIT_DESKTOP_MODE, wct) + } else { + shellTaskOrganizer.applyTransaction(wct) + } + } + /** Move a task to the front **/ fun moveTaskToFront(taskInfo: ActivityManager.RunningTaskInfo) { val wct = WindowContainerTransaction() @@ -396,9 +410,9 @@ class DesktopTasksController( val statusBarHeight = displayController .getDisplayLayout(taskInfo.displayId)?.stableInsets()?.top ?: 0 if (y <= statusBarHeight && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) { - moveToFullscreen(taskInfo.taskId) visualIndicator?.releaseFullscreenIndicator() visualIndicator = null + moveToFullscreenWithAnimation(taskInfo) } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java new file mode 100644 index 000000000000..d18e98af0988 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.desktopmode; + +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; + +import android.animation.ValueAnimator; +import android.app.ActivityManager; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.IBinder; +import android.util.DisplayMetrics; +import android.view.SurfaceControl; +import android.view.WindowManager; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; +import android.window.WindowContainerTransaction; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.wm.shell.transition.Transitions; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + + +/** + * The {@link Transitions.TransitionHandler} that handles transitions for desktop mode tasks + * entering and exiting freeform. + */ +public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionHandler { + private static final int FULLSCREEN_ANIMATION_DURATION = 336; + private final Context mContext; + private final Transitions mTransitions; + private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); + + private Supplier<SurfaceControl.Transaction> mTransactionSupplier; + + public ExitDesktopTaskTransitionHandler( + Transitions transitions, + Context context) { + this(transitions, SurfaceControl.Transaction::new, context); + } + + private ExitDesktopTaskTransitionHandler( + Transitions transitions, + Supplier<SurfaceControl.Transaction> supplier, + Context context) { + mTransitions = transitions; + mTransactionSupplier = supplier; + mContext = context; + } + + /** + * Starts Transition of a given type + * @param type Transition type + * @param wct WindowContainerTransaction for transition + */ + public void startTransition(@WindowManager.TransitionType int type, + @NonNull WindowContainerTransaction wct) { + final IBinder token = mTransitions.startTransition(type, wct, this); + mPendingTransitionTokens.add(token); + } + + @Override + public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startT, + @NonNull SurfaceControl.Transaction finishT, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + boolean transitionHandled = false; + for (TransitionInfo.Change change : info.getChanges()) { + if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { + continue; + } + + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (taskInfo == null || taskInfo.taskId == -1) { + continue; + } + + if (change.getMode() == WindowManager.TRANSIT_CHANGE) { + transitionHandled |= startChangeTransition( + transition, info.getType(), change, startT, finishCallback); + } + } + + mPendingTransitionTokens.remove(transition); + + return transitionHandled; + } + + @VisibleForTesting + boolean startChangeTransition( + @NonNull IBinder transition, + @WindowManager.TransitionType int type, + @NonNull TransitionInfo.Change change, + @NonNull SurfaceControl.Transaction startT, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + if (!mPendingTransitionTokens.contains(transition)) { + return false; + } + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (type == Transitions.TRANSIT_EXIT_DESKTOP_MODE + && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + // This Transition animates a task to fullscreen after being dragged to status bar + final Resources resources = mContext.getResources(); + final DisplayMetrics metrics = resources.getDisplayMetrics(); + final int screenWidth = metrics.widthPixels; + final int screenHeight = metrics.heightPixels; + final SurfaceControl sc = change.getLeash(); + startT.setCrop(sc, null); + startT.apply(); + final ValueAnimator animator = new ValueAnimator(); + animator.setFloatValues(0f, 1f); + animator.setDuration(FULLSCREEN_ANIMATION_DURATION); + final Rect startBounds = change.getStartAbsBounds(); + final float scaleX = (float) startBounds.width() / screenWidth; + final float scaleY = (float) startBounds.height() / screenHeight; + final SurfaceControl.Transaction t = mTransactionSupplier.get(); + Point startPos = new Point(startBounds.left, + startBounds.top); + animator.addUpdateListener(animation -> { + float fraction = animation.getAnimatedFraction(); + float currentScaleX = scaleX + ((1 - scaleX) * fraction); + float currentScaleY = scaleY + ((1 - scaleY) * fraction); + t.setPosition(sc, startPos.x * (1 - fraction), startPos.y * (1 - fraction)); + t.setScale(sc, currentScaleX, currentScaleY); + t.apply(); + }); + animator.start(); + return true; + } + + return false; + } + + @Nullable + @Override + public WindowContainerTransaction handleRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request) { + return null; + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS index afddfab99a2b..ec09827fa4d1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS @@ -1,2 +1,3 @@ # WM shell sub-module pip owner hwwang@google.com +mateuszc@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 4c53f607a5f8..f70df833cf4f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -188,6 +188,11 @@ public class PipAnimationController { return mCurrentAnimator; } + /** Reset animator state to prevent it from being used after its lifetime. */ + public void resetAnimatorState() { + mCurrentAnimator = null; + } + private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index f2f30ea7a286..a9392120bcd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -73,6 +73,7 @@ import android.window.TaskOrganizer; import android.window.TaskSnapshot; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; +import android.window.WindowContainerTransactionCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; @@ -142,6 +143,23 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, protected final ShellTaskOrganizer mTaskOrganizer; protected final ShellExecutor mMainExecutor; + // the runnable to execute after WindowContainerTransactions is applied to finish resizing pip + private Runnable mPipFinishResizeWCTRunnable; + + private final WindowContainerTransactionCallback mPipFinishResizeWCTCallback = + new WindowContainerTransactionCallback() { + @Override + public void onTransactionReady(int id, SurfaceControl.Transaction t) { + t.apply(); + + // execute the runnable if non-null after WCT is applied to finish resizing pip + if (mPipFinishResizeWCTRunnable != null) { + mPipFinishResizeWCTRunnable.run(); + mPipFinishResizeWCTRunnable = null; + } + } + }; + // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = new PipAnimationController.PipAnimationCallback() { @@ -416,6 +434,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } /** + * Override if the PiP should always use a fade-in animation during PiP entry. + * + * @return true if the mOneShotAnimationType should always be + * {@link PipAnimationController#ANIM_TYPE_ALPHA}. + */ + protected boolean shouldAlwaysFadeIn() { + return false; + } + + /** + * Whether the menu should get attached as early as possible when entering PiP. + * + * @return whether the menu should be attached before + * {@link PipBoundsAlgorithm#getEntryDestinationBounds()} is called. + */ + protected boolean shouldAttachMenuEarly() { + return false; + } + + /** * Callback when Launcher starts swipe-pip-to-home operation. * @return {@link Rect} for destination bounds. */ @@ -709,17 +747,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return; } + if (shouldAlwaysFadeIn()) { + mOneShotAnimationType = ANIM_TYPE_ALPHA; + } + if (mWaitForFixedRotation) { onTaskAppearedWithFixedRotation(); return; } + if (shouldAttachMenuEarly()) { + mPipMenuController.attach(mLeash); + } final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); Objects.requireNonNull(destinationBounds, "Missing destination bounds"); final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { - mPipMenuController.attach(mLeash); + if (!shouldAttachMenuEarly()) { + mPipMenuController.attach(mLeash); + } final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( info.pictureInPictureParams, currentBounds); scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */, @@ -834,7 +881,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, @Nullable SurfaceControl.Transaction boundsChangeTransaction) { // PiP menu is attached late in the process here to avoid any artifacts on the leash // caused by addShellRoot when in gesture navigation mode. - mPipMenuController.attach(mLeash); + if (!shouldAttachMenuEarly()) { + mPipMenuController.attach(mLeash); + } final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); wct.setBounds(mToken, destinationBounds); @@ -1249,8 +1298,23 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, /** * Animates resizing of the pinned stack given the duration and start bounds. * This is used when the starting bounds is not the current PiP bounds. + * + * @param pipFinishResizeWCTRunnable callback to run after window updates are complete */ public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration, + float startingAngle, Consumer<Rect> updateBoundsCallback, + Runnable pipFinishResizeWCTRunnable) { + mPipFinishResizeWCTRunnable = pipFinishResizeWCTRunnable; + if (mPipFinishResizeWCTRunnable != null) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "mPipFinishResizeWCTRunnable is set to be called once window updates"); + } + + scheduleAnimateResizePip(fromBounds, toBounds, duration, startingAngle, + updateBoundsCallback); + } + + private void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration, float startingAngle, Consumer<Rect> updateBoundsCallback) { if (mWaitForFixedRotation) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, @@ -1555,7 +1619,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSplitScreenOptional.ifPresent(splitScreenController -> splitScreenController.enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct)); } else { - mTaskOrganizer.applyTransaction(wct); + mTaskOrganizer.applySyncTransaction(wct, mPipFinishResizeWCTCallback); } } @@ -1790,6 +1854,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, animator::clearContentOverlay); } PipAnimationController.quietCancel(animator); + mPipAnimationController.resetAnimatorState(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 49a27c57dc73..4a76a502462c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -272,6 +272,8 @@ public class PipTransition extends PipTransitionController { public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { if (requestHasPipEnter(request)) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: handle PiP enter request", TAG); WindowContainerTransaction wct = new WindowContainerTransaction(); augmentRequest(transition, request, wct); return wct; @@ -731,6 +733,11 @@ public class PipTransition extends PipTransitionController { setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams, taskInfo.topActivityInfo); + + if (mPipOrganizer.shouldAttachMenuEarly()) { + mPipMenuController.attach(leash); + } + final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds(); int rotationDelta = deltaRotation(startRotation, endRotation); @@ -745,7 +752,10 @@ public class PipTransition extends PipTransitionController { mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); - mTransitions.getMainExecutor().executeDelayed(() -> mPipMenuController.attach(leash), 0); + if (!mPipOrganizer.shouldAttachMenuEarly()) { + mTransitions.getMainExecutor().executeDelayed( + () -> mPipMenuController.attach(leash), 0); + } if (taskInfo.pictureInPictureParams != null && taskInfo.pictureInPictureParams.isAutoEnterEnabled() @@ -785,6 +795,11 @@ public class PipTransition extends PipTransitionController { tmpTransform.postRotate(rotationDelta); startTransaction.setMatrix(leash, tmpTransform, new float[9]); } + + if (mPipOrganizer.shouldAlwaysFadeIn()) { + mOneShotAnimationType = ANIM_TYPE_ALPHA; + } + if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index fee9140d0c2c..956af709f156 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -580,8 +580,16 @@ public class PipResizeGestureHandler { final float snapFraction = mPipBoundsAlgorithm.getSnapFraction( mLastResizeBounds, movementBounds); mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction); + + // disable the pinch resizing until the final bounds are updated + final boolean prevEnablePinchResize = mEnablePinchResize; + mEnablePinchResize = false; + mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds, - PINCH_RESIZE_SNAP_DURATION, mAngle, mUpdateResizeBoundsCallback); + PINCH_RESIZE_SNAP_DURATION, mAngle, mUpdateResizeBoundsCallback, () -> { + // reset the pinch resizing to its default state + mEnablePinchResize = prevEnablePinchResize; + }); } else { mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index d73723cc02ff..2f74fb636bc9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -446,7 +446,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal "%s: PiP has already been closed by custom close action", TAG); return; } - removeTask(mPinnedTaskId); + mPipTaskOrganizer.removePip(); onPipDisappeared(); } @@ -673,17 +673,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal } } - private static void removeTask(int taskId) { - ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "%s: removeTask(), taskId=%d", TAG, taskId); - try { - ActivityTaskManager.getService().removeTask(taskId); - } catch (Exception e) { - ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "%s: Atm.removeTask() failed, %s", TAG, e); - } - } - private static String stateToName(@State int state) { switch (state) { case STATE_NO_PIP: diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java index f6856f15f16f..0940490e9944 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java @@ -85,4 +85,17 @@ public class TvPipTaskOrganizer extends PipTaskOrganizer { mPipParamsChangedForwarder.notifySubtitleChanged(params.getSubtitle()); } } + + /** + * Override for TV since the menu bounds affect the PiP location. Additionally, we want to + * ensure that menu is shown immediately since it should always be visible on TV as it creates + * a border with rounded corners around the PiP. + */ + protected boolean shouldAttachMenuEarly() { + return true; + } + + protected boolean shouldAlwaysFadeIn() { + return true; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java index 8ebcf63f36e9..d3253a5e4d94 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java @@ -16,60 +16,43 @@ package com.android.wm.shell.pip.tv; -import android.app.TaskInfo; -import android.graphics.Rect; -import android.os.IBinder; -import android.view.SurfaceControl; -import android.window.TransitionInfo; -import android.window.TransitionRequestInfo; -import android.window.WindowContainerTransaction; +import android.content.Context; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.pip.PipAnimationController; -import com.android.wm.shell.pip.PipBoundsState; -import com.android.wm.shell.pip.PipMenuController; -import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.pip.PipDisplayLayoutState; +import com.android.wm.shell.pip.PipSurfaceTransactionHelper; +import com.android.wm.shell.pip.PipTransition; +import com.android.wm.shell.pip.PipTransitionState; +import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; +import java.util.Optional; + /** * PiP Transition for TV. - * TODO: Implement animation once TV is using Transitions. */ -public class TvPipTransition extends PipTransitionController { - public TvPipTransition( +public class TvPipTransition extends PipTransition { + + public TvPipTransition(Context context, @NonNull ShellInit shellInit, @NonNull ShellTaskOrganizer shellTaskOrganizer, @NonNull Transitions transitions, - PipBoundsState pipBoundsState, - PipMenuController pipMenuController, + TvPipBoundsState tvPipBoundsState, + PipDisplayLayoutState pipDisplayLayoutState, + PipTransitionState pipTransitionState, + TvPipMenuController tvPipMenuController, TvPipBoundsAlgorithm tvPipBoundsAlgorithm, - PipAnimationController pipAnimationController) { - super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, - tvPipBoundsAlgorithm, pipAnimationController); - } - - @Override - public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, int direction, - SurfaceControl.Transaction tx) { - - } - - @Override - public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, - @NonNull SurfaceControl.Transaction startTransaction, - @android.annotation.NonNull SurfaceControl.Transaction finishTransaction, - @NonNull Transitions.TransitionFinishCallback finishCallback) { - return false; + PipAnimationController pipAnimationController, + PipSurfaceTransactionHelper pipSurfaceTransactionHelper, + Optional<SplitScreenController> splitScreenOptional) { + super(context, shellInit, shellTaskOrganizer, transitions, tvPipBoundsState, + pipDisplayLayoutState, pipTransitionState, tvPipMenuController, + tvPipBoundsAlgorithm, pipAnimationController, pipSurfaceTransactionHelper, + splitScreenOptional); } - @Nullable - @Override - public WindowContainerTransaction handleRequest(@NonNull IBinder transition, - @NonNull TransitionRequestInfo request) { - return null; - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index 5c64177ae835..c8d6a5e8e00b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -456,7 +456,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { cancel(mWillFinishToHome); return; } - hasChangingApp = true; + // Don't consider order-only changes as changing apps. + if (!TransitionUtil.isOrderOnly(change)) { + hasChangingApp = true; + } } } if (hasChangingApp && foundRecentsClosing) { @@ -484,13 +487,14 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } boolean didMergeThings = false; if (closingTasks != null) { - // Cancelling a task-switch. Move the tasks back to mPausing from mOpening + // Potentially cancelling a task-switch. Move the tasks back to mPausing if they + // are in mOpening. for (int i = 0; i < closingTasks.size(); ++i) { final TransitionInfo.Change change = closingTasks.get(i); int openingIdx = TaskState.indexOf(mOpeningTasks, change); if (openingIdx < 0) { - Slog.e(TAG, "Back to existing recents animation from an unrecognized " - + "task: " + change.getTaskInfo().taskId); + Slog.w(TAG, "Closing a task that wasn't opening, this may be split or" + + " something unexpected: " + change.getTaskInfo().taskId); continue; } mPausingTasks.add(mOpeningTasks.remove(openingIdx)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index d52abf795152..5a92f7830194 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -235,6 +235,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, private TransitionInfo subCopy(@NonNull TransitionInfo info, @WindowManager.TransitionType int newType, boolean withChanges) { final TransitionInfo out = new TransitionInfo(newType, withChanges ? info.getFlags() : 0); + out.setDebugId(info.getDebugId()); if (withChanges) { for (int i = 0; i < info.getChanges().size(); ++i) { out.getChanges().add(info.getChanges().get(i)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 63c7969291a0..3dd10a098310 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -301,8 +301,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { return true; } - // check if no-animation and skip animation if so. - if (Transitions.isAllNoAnimation(info)) { + // Early check if the transition doesn't warrant an animation. + if (Transitions.isAllNoAnimation(info) || Transitions.isAllOrderOnly(info)) { startTransaction.apply(); finishTransaction.apply(); finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java index 485b400f458d..4e3d220f1ea2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java @@ -63,7 +63,7 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { @NonNull Transitions.TransitionFinishCallback finishCallback) { if (mTransition != transition) return false; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Using registered One-shot remote" - + " transition %s for %s.", mRemote, transition); + + " transition %s for #%d.", mRemote, info.getDebugId()); final IBinder.DeathRecipient remoteDied = () -> { Log.e(Transitions.TAG, "Remote transition died, finishing"); @@ -113,9 +113,6 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Using registered One-shot remote" - + " transition %s for %s.", mRemote, transition); - IRemoteTransitionFinishedCallback cb = new IRemoteTransitionFinishedCallback.Stub() { @Override public void onTransitionFinished(WindowContainerTransaction wct, @@ -154,4 +151,10 @@ public class OneShotRemoteHandler implements Transitions.TransitionHandler { + " for %s: %s", transition, remote); return new WindowContainerTransaction(); } + + @Override + public String toString() { + return "OneShotRemoteHandler:" + mRemote.getDebugName() + ":" + + mRemote.getRemoteTransition(); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java index 3c4e8898f215..5b7231c5a5fb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java @@ -101,8 +101,8 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { } RemoteTransition pendingRemote = mRequestedRemotes.get(transition); if (pendingRemote == null) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s doesn't have " - + "explicit remote, search filters for match for %s", transition, info); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition doesn't have " + + "explicit remote, search filters for match for %s", info); // If no explicit remote, search filters until one matches for (int i = mFilters.size() - 1; i >= 0; --i) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Checking filter %s", @@ -116,8 +116,8 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { } } } - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Delegate animation for %s to %s", - transition, pendingRemote); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Delegate animation for #%d to %s", + info.getDebugId(), pendingRemote); if (pendingRemote == null) return false; @@ -184,9 +184,10 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { - final IRemoteTransition remote = mRequestedRemotes.get(mergeTarget).getRemoteTransition(); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Attempt merge %s into %s", - transition, remote); + final RemoteTransition remoteTransition = mRequestedRemotes.get(mergeTarget); + final IRemoteTransition remote = remoteTransition.getRemoteTransition(); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Merge into remote: %s", + remoteTransition); if (remote == null) return; IRemoteTransitionFinishedCallback cb = new IRemoteTransitionFinishedCallback.Stub() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java index 0386ec38a3ff..1879bf721fed 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java @@ -19,7 +19,6 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; -import android.util.Log; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; @@ -59,7 +58,6 @@ class SleepHandler implements Transitions.TransitionHandler { @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishTransaction) { - Log.e(Transitions.TAG, "Sleep transition was consumed. This doesn't make sense"); mSleepTransitions.remove(transition); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index 4284993a5448..681fa5177da2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -140,6 +140,9 @@ public class Transitions implements RemoteCallable<Transitions> { /** Transition type to freeform in desktop mode. */ public static final int TRANSIT_ENTER_DESKTOP_MODE = WindowManager.TRANSIT_FIRST_CUSTOM + 11; + /** Transition type to fullscreen from desktop mode. */ + public static final int TRANSIT_EXIT_DESKTOP_MODE = WindowManager.TRANSIT_FIRST_CUSTOM + 12; + private final WindowOrganizer mOrganizer; private final Context mContext; private final ShellExecutor mMainExecutor; @@ -182,6 +185,14 @@ public class Transitions implements RemoteCallable<Transitions> { /** Ordered list of transitions which have been merged into this one. */ private ArrayList<ActiveTransition> mMerged; + + @Override + public String toString() { + if (mInfo != null && mInfo.getDebugId() >= 0) { + return "(#" + mInfo.getDebugId() + ")" + mToken; + } + return mToken.toString(); + } } /** Keeps track of transitions which have been started, but aren't ready yet. */ @@ -516,6 +527,16 @@ public class Transitions implements RemoteCallable<Transitions> { return hasNoAnimation; } + /** + * Check if all changes in this transition are only ordering changes. If so, we won't animate. + */ + static boolean isAllOrderOnly(TransitionInfo info) { + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + if (!TransitionUtil.isOrderOnly(info.getChanges().get(i))) return false; + } + return true; + } + @VisibleForTesting void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) { @@ -529,8 +550,8 @@ public class Transitions implements RemoteCallable<Transitions> { activeTransition -> activeTransition.mToken).toArray())); } if (activeIdx > 0) { - Log.e(TAG, "Transition became ready out-of-order " + transitionToken + ". Expected" - + " order: " + Arrays.toString(mPendingTransitions.stream().map( + Log.e(TAG, "Transition became ready out-of-order " + mPendingTransitions.get(activeIdx) + + ". Expected order: " + Arrays.toString(mPendingTransitions.stream().map( activeTransition -> activeTransition.mToken).toArray())); } // Move from pending to ready @@ -547,6 +568,7 @@ public class Transitions implements RemoteCallable<Transitions> { if (info.getType() == TRANSIT_SLEEP) { if (activeIdx > 0 || !mActiveTransitions.isEmpty() || mReadyTransitions.size() > 1) { // Sleep starts a process of forcing all prior transitions to finish immediately + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Start finish-for-sleep"); finishForSleep(null /* forceFinish */); return; } @@ -555,8 +577,8 @@ public class Transitions implements RemoteCallable<Transitions> { if (info.getRootCount() == 0 && !alwaysReportToKeyguard(info)) { // No root-leashes implies that the transition is empty/no-op, so just do // housekeeping and return. - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "No transition roots (%s): %s", - transitionToken, info); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "No transition roots in %s so" + + " abort", active); onAbort(active); return; } @@ -585,6 +607,8 @@ public class Transitions implements RemoteCallable<Transitions> { && allOccluded)) { // Treat this as an abort since we are bypassing any merge logic and effectively // finishing immediately. + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, + "Non-visible anim so abort: %s", active); onAbort(active); return; } @@ -652,21 +676,21 @@ public class Transitions implements RemoteCallable<Transitions> { return; } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s ready while" - + " another transition %s is still animating. Notify the animating transition" - + " in case they can be merged", ready.mToken, playing.mToken); + + " %s is still animating. Notify the animating transition" + + " in case they can be merged", ready, playing); playing.mHandler.mergeAnimation(ready.mToken, ready.mInfo, ready.mStartT, playing.mToken, (wct, cb) -> onMerged(playing, ready)); } private void onMerged(@NonNull ActiveTransition playing, @NonNull ActiveTransition merged) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged %s", - merged.mToken); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged: %s into %s", + merged, playing); int readyIdx = 0; if (mReadyTransitions.isEmpty() || mReadyTransitions.get(0) != merged) { - Log.e(TAG, "Merged transition out-of-order?"); + Log.e(TAG, "Merged transition out-of-order? " + merged); readyIdx = mReadyTransitions.indexOf(merged); if (readyIdx < 0) { - Log.e(TAG, "Merged a transition that is no-longer queued?"); + Log.e(TAG, "Merged a transition that is no-longer queued? " + merged); return; } } @@ -687,6 +711,7 @@ public class Transitions implements RemoteCallable<Transitions> { } private void playTransition(@NonNull ActiveTransition active) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Playing animation for %s", active); for (int i = 0; i < mObservers.size(); ++i) { mObservers.get(i).onTransitionStarting(active.mToken); } @@ -788,12 +813,12 @@ public class Transitions implements RemoteCallable<Transitions> { int activeIdx = mActiveTransitions.indexOf(active); if (activeIdx < 0) { Log.e(TAG, "Trying to finish a non-running transition. Either remote crashed or " - + " a handler didn't properly deal with a merge. " + active.mToken, + + " a handler didn't properly deal with a merge. " + active, new RuntimeException()); return; } else if (activeIdx != 0) { // Relevant right now since we only allow 1 active transition at a time. - Log.e(TAG, "Finishing a transition out of order. " + active.mToken); + Log.e(TAG, "Finishing a transition out of order. " + active); } mActiveTransitions.remove(activeIdx); @@ -801,7 +826,7 @@ public class Transitions implements RemoteCallable<Transitions> { mObservers.get(i).onTransitionFinished(active.mToken, active.mAborted); } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished " - + "(aborted=%b), notifying core %s", active.mAborted, active.mToken); + + "(aborted=%b), notifying core %s", active.mAborted, active); if (active.mStartT != null) { // Applied by now, so clear immediately to remove any references. Do not set to null // yet, though, since nullness is used later to disambiguate malformed transitions. @@ -917,6 +942,8 @@ public class Transitions implements RemoteCallable<Transitions> { /** Start a new transition directly. */ public IBinder startTransition(@WindowManager.TransitionType int type, @NonNull WindowContainerTransaction wct, @Nullable TransitionHandler handler) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Directly starting a new transition " + + "type=%d wct=%s handler=%s", type, wct, handler); final ActiveTransition active = new ActiveTransition(); active.mHandler = handler; active.mToken = mOrganizer.startNewTransition(type, wct); @@ -948,8 +975,7 @@ public class Transitions implements RemoteCallable<Transitions> { return; } if (forceFinish != null && mActiveTransitions.contains(forceFinish)) { - Log.e(TAG, "Forcing transition to finish due to sleep timeout: " - + forceFinish.mToken); + Log.e(TAG, "Forcing transition to finish due to sleep timeout: " + forceFinish); forceFinish.mAborted = true; // Last notify of it being consumed. Note: mHandler should never be null, // but check just to be safe. @@ -967,6 +993,8 @@ public class Transitions implements RemoteCallable<Transitions> { // Try to signal that we are sleeping by attempting to merge the sleep transition // into the playing one. final ActiveTransition nextSleep = mReadyTransitions.get(sleepIdx); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Attempt to merge SLEEP %s" + + " into %s", nextSleep, playing); playing.mHandler.mergeAnimation(nextSleep.mToken, nextSleep.mInfo, dummyT, playing.mToken, (wct, cb) -> {}); } else { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java index 7595c9617709..ce102917352d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java @@ -31,6 +31,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; +import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; @@ -90,6 +91,15 @@ public class TransitionUtil { && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY); } + /** Returns `true` if `change` is only re-ordering. */ + public static boolean isOrderOnly(TransitionInfo.Change change) { + return change.getMode() == TRANSIT_CHANGE + && (change.getFlags() & FLAG_MOVED_TO_TOP) != 0 + && change.getStartAbsBounds().equals(change.getEndAbsBounds()) + && (change.getLastParent() == null + || change.getLastParent().equals(change.getParent())); + } + /** * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you * MUST call `test` in the same order that the changes appear in the TransitionInfo. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java index 8cb575cc96e3..2cd1e1d558ae 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java @@ -42,6 +42,9 @@ import android.view.WindowManagerGlobal; import com.android.internal.view.BaseIWindow; +import java.util.Arrays; +import java.util.List; + /** * An input event listener registered to InputDispatcher to receive input events on task edges and * and corners. Converts them to drag resize requests. @@ -211,6 +214,10 @@ class DragResizeInputListener implements AutoCloseable { PRIVATE_FLAG_TRUSTED_OVERLAY, 0 /* inputFeatures */, touchRegion); + List<Rect> cornersList = Arrays.asList( + mLeftTopCornerBounds, mLeftBottomCornerBounds, + mRightTopCornerBounds, mRightBottomCornerBounds); + mWindowSession.reportSystemGestureExclusionChanged(mFakeWindow, cornersList); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt index 91846fafd1db..e986ee127708 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt @@ -218,36 +218,36 @@ fun FlickerTest.splitAppLayerBoundsChanges( assertLayers { if (landscapePosLeft) { splitAppLayerBoundsSnapToDivider( - component, - landscapePosLeft, - portraitPosTop, - scenario.endRotation - ) - .then() - .isInvisible(component) - .then() - .splitAppLayerBoundsSnapToDivider( - component, - landscapePosLeft, - portraitPosTop, - scenario.endRotation - ) + component, + landscapePosLeft, + portraitPosTop, + scenario.endRotation + ) + .then() + .isInvisible(component) + .then() + .splitAppLayerBoundsSnapToDivider( + component, + landscapePosLeft, + portraitPosTop, + scenario.endRotation + ) } else { splitAppLayerBoundsSnapToDivider( - component, - landscapePosLeft, - portraitPosTop, - scenario.endRotation - ) - .then() - .isInvisible(component) - .then() - .splitAppLayerBoundsSnapToDivider( - component, - landscapePosLeft, - portraitPosTop, - scenario.endRotation - ) + component, + landscapePosLeft, + portraitPosTop, + scenario.endRotation + ) + .then() + .isInvisible(component) + .then() + .splitAppLayerBoundsSnapToDivider( + component, + landscapePosLeft, + portraitPosTop, + scenario.endRotation + ) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt index d0bca1332553..2474ecf74cf9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt @@ -17,8 +17,8 @@ package com.android.wm.shell.flicker.bubble import android.os.SystemClock +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -26,8 +26,6 @@ import androidx.test.filters.RequiresDevice import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.Until -import org.junit.Assume -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -45,13 +43,8 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FlakyTest(bugId = 217777115) open class ChangeActiveActivityFromBubbleTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) { - - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - /** {@inheritDoc} */ override val transition: FlickerBuilder.() -> Unit get() = buildTransition { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt deleted file mode 100644 index 5e85eb87e0e9..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.flicker.bubble - -import android.platform.test.annotations.FlakyTest -import android.tools.device.flicker.isShellTransitionsEnabled -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerTest -import androidx.test.filters.RequiresDevice -import org.junit.Assume -import org.junit.Before -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FlakyTest(bugId = 217777115) -class ChangeActiveActivityFromBubbleTestShellTransit(flicker: FlickerTest) : - ChangeActiveActivityFromBubbleTest(flicker) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt index 1045a5ac2ce8..93ee6992a98f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt @@ -40,6 +40,7 @@ import org.junit.runners.Parameterized * Select "Auto-enter PiP" radio button * Press Home button or swipe up to go Home and put [pipApp] in pip mode * ``` + * * Notes: * ``` * 1. All assertions are inherited from [EnterPipTest] diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt index 2d2588ef4348..59918fb7b6a9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt @@ -38,6 +38,7 @@ import org.junit.runners.Parameterized * Launch an app in pip mode [pipApp], * Swipe the pip window to the bottom-center of the screen and wait it disappear * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt index 6c5a344c8f79..36c6f7c438c4 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt @@ -19,7 +19,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit import android.tools.common.Rotation import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest import android.tools.device.flicker.legacy.FlickerTestFactory @@ -43,25 +42,17 @@ abstract class ClosePipTransition(flicker: FlickerTest) : PipTransition(flicker) @Presubmit @Test open fun pipWindowBecomesInvisible() { - if (isShellTransitionsEnabled) { - // When Shell transition is enabled, we change the windowing mode at start, but - // update the visibility after the transition is finished, so we can't check isNotPinned - // and isAppWindowInvisible in the same assertion block. - flicker.assertWm { - this.invoke("hasPipWindow") { - it.isPinned(pipApp).isAppWindowVisible(pipApp).isAppWindowOnTop(pipApp) - } - .then() - .invoke("!hasPipWindow") { it.isNotPinned(pipApp).isAppWindowNotOnTop(pipApp) } - } - flicker.assertWmEnd { isAppWindowInvisible(pipApp) } - } else { - flicker.assertWm { - this.invoke("hasPipWindow") { it.isPinned(pipApp).isAppWindowVisible(pipApp) } - .then() - .invoke("!hasPipWindow") { it.isNotPinned(pipApp).isAppWindowInvisible(pipApp) } - } + // When Shell transition is enabled, we change the windowing mode at start, but + // update the visibility after the transition is finished, so we can't check isNotPinned + // and isAppWindowInvisible in the same assertion block. + flicker.assertWm { + this.invoke("hasPipWindow") { + it.isPinned(pipApp).isAppWindowVisible(pipApp).isAppWindowOnTop(pipApp) + } + .then() + .invoke("!hasPipWindow") { it.isNotPinned(pipApp).isAppWindowNotOnTop(pipApp) } } + flicker.assertWmEnd { isAppWindowInvisible(pipApp) } } /** diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt index e540ad543228..d16583271e8c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt @@ -38,6 +38,7 @@ import org.junit.runners.Parameterized * Click on the pip window * Click on dismiss button and wait window disappear * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt index e079d5477e2f..db18edba9cc4 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt @@ -53,6 +53,7 @@ import org.junit.runners.Parameterized * Launch [pipApp] on a fixed landscape orientation * Broadcast action [ACTION_ENTER_PIP] to enter pip mode * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt index e40e5eaad9e2..51f01364ec9c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt @@ -44,9 +44,7 @@ abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker) @Presubmit @Test open fun pipAppLayerAlwaysVisible() { - flicker.assertLayers { - this.isVisible(pipApp) - } + flicker.assertLayers { this.isVisible(pipApp) } } /** Checks the content overlay appears then disappears during the animation */ @@ -55,11 +53,7 @@ abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker) open fun pipOverlayLayerAppearThenDisappear() { val overlay = ComponentNameMatcher.PIP_CONTENT_OVERLAY flicker.assertLayers { - this.notContains(overlay) - .then() - .contains(overlay) - .then() - .notContains(overlay) + this.notContains(overlay).then().contains(overlay).then().notContains(overlay) } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt index 1f060e931be2..f1925d8c9d85 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt @@ -35,6 +35,7 @@ import org.junit.runners.Parameterized * Launch an app in full screen * Press an "enter pip" button to put [pipApp] in pip mode * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt index 313631cbe8ee..3e0e37dfc997 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt @@ -16,16 +16,11 @@ package com.android.wm.shell.flicker.pip -import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest import androidx.test.filters.RequiresDevice -import org.junit.Assume import org.junit.FixMethodOrder -import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized @@ -42,6 +37,7 @@ import org.junit.runners.Parameterized * Expand [pipApp] app to full screen by clicking on the pip window and * then on the expand button * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) @@ -72,19 +68,4 @@ open class ExitPipToAppViaExpandButtonTest(flicker: FlickerTest) : ExitPipToAppT wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify() } } - - /** {@inheritDoc} */ - @FlakyTest(bugId = 197726610) - @Test - override fun pipLayerExpands() { - Assume.assumeFalse(isShellTransitionsEnabled) - super.pipLayerExpands() - } - - @Presubmit - @Test - fun pipLayerExpands_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) - super.pipLayerExpands() - } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt index 93ffdd8d5294..603f99541a12 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt @@ -16,16 +16,11 @@ package com.android.wm.shell.flicker.pip -import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest import androidx.test.filters.RequiresDevice -import org.junit.Assume import org.junit.FixMethodOrder -import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized @@ -41,6 +36,7 @@ import org.junit.runners.Parameterized * Launch another full screen mode [testApp] * Expand [pipApp] app to full screen via an intent * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) @@ -71,37 +67,4 @@ open class ExitPipToAppViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransit wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify() } } - - /** {@inheritDoc} */ - @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Presubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() { - Assume.assumeFalse(isShellTransitionsEnabled) - super.statusBarLayerPositionAtStartAndEnd() - } - - @Presubmit - @Test - fun statusBarLayerRotatesScales_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) - super.statusBarLayerPositionAtStartAndEnd() - } - - /** {@inheritDoc} */ - @FlakyTest(bugId = 197726610) - @Test - override fun pipLayerExpands() { - Assume.assumeFalse(isShellTransitionsEnabled) - super.pipLayerExpands() - } - - @Presubmit - @Test - fun pipLayerExpands_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) - super.pipLayerExpands() - } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt index 7d5f740838bd..6deba1b68f38 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt @@ -40,6 +40,7 @@ import org.junit.runners.Parameterized * Launch an app in pip mode [pipApp], * Expand [pipApp] app to its maximum pip size by double clicking on it * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt index 9c007449fb8d..d8d57d219933 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt @@ -40,6 +40,7 @@ import org.junit.runners.Parameterized * Launch [testApp] * Check if pip window moves down (visually) * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt index c23838a987bf..a626713aaa11 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt @@ -19,7 +19,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit import android.tools.common.Rotation import android.tools.common.datatypes.component.ComponentNameMatcher -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -28,8 +27,6 @@ import android.tools.device.helpers.WindowUtils import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.ImeAppHelper import com.android.server.wm.flicker.helpers.setRotation -import org.junit.Assume.assumeFalse -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -44,11 +41,6 @@ import org.junit.runners.Parameterized open class MovePipOnImeVisibilityChangeTest(flicker: FlickerTest) : PipTransition(flicker) { private val imeApp = ImeAppHelper(instrumentation) - @Before - open fun before() { - assumeFalse(isShellTransitionsEnabled) - } - /** {@inheritDoc} */ override val transition: FlickerBuilder.() -> Unit get() = buildTransition { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt deleted file mode 100644 index 6f8111690f0f..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.flicker.pip - -import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.isShellTransitionsEnabled -import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.tools.device.flicker.legacy.FlickerTest -import androidx.test.filters.RequiresDevice -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class MovePipOnImeVisibilityChangeTestShellTransit(flicker: FlickerTest) : - MovePipOnImeVisibilityChangeTest(flicker) { - - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } - - @Presubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd() -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt index c8d5624b1d77..ae3f87967658 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt @@ -40,6 +40,7 @@ import org.junit.runners.Parameterized * Press home * Check if pip window moves up (visually) * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt index 083cfd294f96..4e2a4e700698 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt @@ -30,9 +30,7 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized -/** - * Test the dragging of a PIP window. - */ +/** Test the dragging of a PIP window. */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @@ -59,9 +57,7 @@ class PipDragTest(flicker: FlickerTest) : PipTransition(flicker) { pipApp.exit(wmHelper) tapl.setEnableRotation(false) } - transitions { - pipApp.dragPipWindowAwayFromEdgeWithoutRelease(wmHelper, 50) - } + transitions { pipApp.dragPipWindowAwayFromEdgeWithoutRelease(wmHelper, 50) } } @Postsubmit @@ -92,4 +88,4 @@ class PipDragTest(flicker: FlickerTest) : PipTransition(flicker) { return FlickerTestFactory.nonRotationTests() } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt index 53ce3936fbe4..9fe9f52fd4af 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt @@ -16,10 +16,10 @@ package com.android.wm.shell.flicker.pip +import android.graphics.Rect import android.platform.test.annotations.Postsubmit import android.tools.common.Rotation import android.tools.device.flicker.junit.FlickerParametersRunnerFactory -import android.graphics.Rect import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest import android.tools.device.flicker.legacy.FlickerTestFactory @@ -33,14 +33,12 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized -/** - * Test the snapping of a PIP window via dragging, releasing, and checking its final location. - */ +/** Test the snapping of a PIP window via dragging, releasing, and checking its final location. */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker){ +class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker) { // represents the direction in which the pip window should be snapping private var willSnapRight: Boolean = true @@ -60,8 +58,12 @@ class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker){ // get the initial region bounds and cache them val initRegion = pipApp.getWindowRect(wmHelper) - startBounds - .set(initRegion.left, initRegion.top, initRegion.right, initRegion.bottom) + startBounds.set( + initRegion.left, + initRegion.top, + initRegion.right, + initRegion.bottom + ) // drag the pip window away from the edge pipApp.dragPipWindowAwayFromEdge(wmHelper, 50) @@ -108,4 +110,4 @@ class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker){ ) } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt index 2cf8f61f13fe..703784dd8c67 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt @@ -43,6 +43,7 @@ import org.junit.runners.Parameterized * Rotate the screen from [flicker.scenario.startRotation] to [flicker.scenario.endRotation] * (usually, 0->90 and 90->0) * ``` + * * Notes: * ``` * 1. Some default assertions (e.g., nav bar, status bar and screen covered) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt index 17f174b2195f..5180791276a2 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt @@ -16,9 +16,9 @@ package com.android.wm.shell.flicker.splitscreen +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Presubmit -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -107,18 +107,15 @@ class DragDividerToResize(flicker: FlickerTest) : SplitScreenBase(flicker) { } } - @Presubmit - @Test - fun primaryAppWindowKeepVisible() = flicker.appWindowKeepVisible(primaryApp) + @Presubmit @Test fun primaryAppWindowKeepVisible() = flicker.appWindowKeepVisible(primaryApp) @Presubmit @Test fun secondaryAppWindowKeepVisible() = flicker.appWindowKeepVisible(secondaryApp) - @Presubmit + @FlakyTest(bugId = 245472831) @Test fun primaryAppBoundsChanges() { - Assume.assumeFalse(isShellTransitionsEnabled) flicker.splitAppLayerBoundsChanges( primaryApp, landscapePosLeft = true, @@ -135,11 +132,6 @@ class DragDividerToResize(flicker: FlickerTest) : SplitScreenBase(flicker) { portraitPosTop = true ) - /** {@inheritDoc} */ - @Presubmit - @Test - override fun entireScreenCovered() = super.entireScreenCovered() - companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt index 5b06c9c3897d..69da1e29a19c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.tools.common.NavBar -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -79,21 +79,24 @@ class EnterSplitScreenByDragFromAllApps(flicker: FlickerTest) : SplitScreenBase( @IwTest(focusArea = "sysui") @Presubmit @Test - fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = false, - appExistAtStart = false) + fun cujCompleted() = + flicker.splitScreenEntered( + primaryApp, + secondaryApp, + fromOtherApp = false, + appExistAtStart = false + ) - @Presubmit + @FlakyTest(bugId = 245472831) @Test fun splitScreenDividerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) flicker.splitScreenDividerBecomesVisible() } // TODO(b/245472831): Back to splitScreenDividerBecomesVisible after shell transition ready. @Presubmit @Test - fun splitScreenDividerIsVisibleAtEnd_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) + fun splitScreenDividerIsVisibleAtEnd() { flicker.assertLayersEnd { this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT) } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt index c8401831bdbc..1773846c18e9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.tools.common.NavBar -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -82,21 +82,19 @@ class EnterSplitScreenByDragFromNotification(flicker: FlickerTest) : SplitScreen @IwTest(focusArea = "sysui") @Presubmit @Test - fun cujCompleted() = flicker.splitScreenEntered(primaryApp, sendNotificationApp, - fromOtherApp = false) + fun cujCompleted() = + flicker.splitScreenEntered(primaryApp, sendNotificationApp, fromOtherApp = false) - @Presubmit + @FlakyTest(bugId = 245472831) @Test fun splitScreenDividerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) flicker.splitScreenDividerBecomesVisible() } // TODO(b/245472831): Back to splitScreenDividerBecomesVisible after shell transition ready. @Presubmit @Test - fun splitScreenDividerIsVisibleAtEnd_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) + fun splitScreenDividerIsVisibleAtEnd() { flicker.assertLayersEnd { this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT) } } @@ -105,23 +103,6 @@ class EnterSplitScreenByDragFromNotification(flicker: FlickerTest) : SplitScreen @Presubmit @Test fun secondaryAppLayerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) - flicker.assertLayers { - this.isInvisible(sendNotificationApp) - .then() - .isVisible(sendNotificationApp) - .then() - .isInvisible(sendNotificationApp) - .then() - .isVisible(sendNotificationApp) - } - } - - // TODO(b/245472831): Align to legacy transition after shell transition ready. - @Presubmit - @Test - fun secondaryAppLayerBecomesVisible_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) flicker.layerBecomesVisible(sendNotificationApp) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt index 5c9920970761..3bea66ef0a27 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt @@ -16,11 +16,11 @@ package com.android.wm.shell.flicker.splitscreen +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.tools.common.NavBar -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -80,21 +80,24 @@ class EnterSplitScreenByDragFromTaskbar(flicker: FlickerTest) : SplitScreenBase( @IwTest(focusArea = "sysui") @Presubmit @Test - fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = false, - appExistAtStart = false) + fun cujCompleted() = + flicker.splitScreenEntered( + primaryApp, + secondaryApp, + fromOtherApp = false, + appExistAtStart = false + ) - @Presubmit + @FlakyTest(bugId = 245472831) @Test fun splitScreenDividerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) flicker.splitScreenDividerBecomesVisible() } // TODO(b/245472831): Back to splitScreenDividerBecomesVisible after shell transition ready. @Presubmit @Test - fun splitScreenDividerIsVisibleAtEnd_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) + fun splitScreenDividerIsVisibleAtEnd() { flicker.assertLayersEnd { this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT) } } @@ -103,23 +106,6 @@ class EnterSplitScreenByDragFromTaskbar(flicker: FlickerTest) : SplitScreenBase( @Presubmit @Test fun secondaryAppLayerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) - flicker.assertLayers { - this.isInvisible(secondaryApp) - .then() - .isVisible(secondaryApp) - .then() - .isInvisible(secondaryApp) - .then() - .isVisible(secondaryApp) - } - } - - // TODO(b/245472831): Align to legacy transition after shell transition ready. - @Presubmit - @Test - fun secondaryAppLayerBecomesVisible_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) flicker.layerBecomesVisible(secondaryApp) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt index 2855c71518eb..9f4cb8c381fc 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -31,7 +30,6 @@ import com.android.wm.shell.flicker.layerBecomesVisible import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible import com.android.wm.shell.flicker.splitScreenEntered -import org.junit.Assume import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -73,19 +71,7 @@ class SwitchBackToSplitFromHome(flicker: FlickerTest) : SplitScreenBase(flicker) @Test fun splitScreenDividerBecomesVisible() = flicker.splitScreenDividerBecomesVisible() - @FlakyTest - @Test - fun primaryAppLayerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) - flicker.layerBecomesVisible(primaryApp) - } - - @Presubmit - @Test - fun primaryAppLayerBecomesVisibleShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) - flicker.layerBecomesVisible(primaryApp) - } + @Presubmit @Test fun primaryAppLayerBecomesVisible() = flicker.layerBecomesVisible(primaryApp) @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt index c29a917c4e7c..a33d8cab9fbd 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.IwTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar -import android.tools.device.flicker.isShellTransitionsEnabled import android.tools.device.flicker.junit.FlickerParametersRunnerFactory import android.tools.device.flicker.legacy.FlickerBuilder import android.tools.device.flicker.legacy.FlickerTest @@ -31,7 +30,6 @@ import com.android.wm.shell.flicker.layerBecomesVisible import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible import com.android.wm.shell.flicker.splitScreenEntered -import org.junit.Assume import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -73,19 +71,7 @@ class SwitchBackToSplitFromRecent(flicker: FlickerTest) : SplitScreenBase(flicke @Test fun splitScreenDividerBecomesVisible() = flicker.splitScreenDividerBecomesVisible() - @FlakyTest - @Test - fun primaryAppLayerBecomesVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) - flicker.layerBecomesVisible(primaryApp) - } - - @Presubmit - @Test - fun primaryAppLayerBecomesVisibleShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) - flicker.layerBecomesVisible(primaryApp) - } + @Presubmit @Test fun primaryAppLayerBecomesVisible() = flicker.layerBecomesVisible(primaryApp) @Presubmit @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 4ccc4678ac5e..c9bd695ffb33 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -81,7 +81,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock lateinit var syncQueue: SyncTransactionQueue @Mock lateinit var rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer @Mock lateinit var transitions: Transitions - @Mock lateinit var transitionHandler: EnterDesktopTaskTransitionHandler + @Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler + @Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler lateinit var mockitoSession: StaticMockitoSession lateinit var controller: DesktopTasksController @@ -117,7 +118,8 @@ class DesktopTasksControllerTest : ShellTestCase() { syncQueue, rootTaskDisplayAreaOrganizer, transitions, - transitionHandler, + enterDesktopTransitionHandler, + exitDesktopTransitionHandler, desktopModeTaskRepository, TestShellExecutor() ) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java new file mode 100644 index 000000000000..2c5a5cd72c53 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.desktopmode; + + +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; + +import static androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.annotation.NonNull; +import android.app.ActivityManager; +import android.app.WindowConfiguration; +import android.content.Context; +import android.content.res.Resources; +import android.os.IBinder; +import android.util.DisplayMetrics; +import android.view.SurfaceControl; +import android.view.WindowManager; +import android.window.IWindowContainerToken; +import android.window.TransitionInfo; +import android.window.WindowContainerToken; +import android.window.WindowContainerTransaction; + +import androidx.test.filters.SmallTest; + +import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.transition.Transitions; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.function.Supplier; + +/** Tests of {@link com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler} */ +@SmallTest +public class ExitDesktopTaskTransitionHandlerTest extends ShellTestCase { + + @Mock + private Transitions mTransitions; + @Mock + IBinder mToken; + @Mock + Supplier<SurfaceControl.Transaction> mTransactionFactory; + @Mock + Context mContext; + @Mock + DisplayMetrics mDisplayMetrics; + @Mock + Resources mResources; + @Mock + SurfaceControl.Transaction mStartT; + @Mock + SurfaceControl.Transaction mFinishT; + @Mock + SurfaceControl.Transaction mAnimationT; + @Mock + Transitions.TransitionFinishCallback mTransitionFinishCallback; + @Mock + ShellExecutor mExecutor; + + private ExitDesktopTaskTransitionHandler mExitDesktopTaskTransitionHandler; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + doReturn(mExecutor).when(mTransitions).getMainExecutor(); + doReturn(mAnimationT).when(mTransactionFactory).get(); + doReturn(mResources).when(mContext).getResources(); + doReturn(mDisplayMetrics).when(mResources).getDisplayMetrics(); + when(mResources.getDisplayMetrics()) + .thenReturn(getContext().getResources().getDisplayMetrics()); + + mExitDesktopTaskTransitionHandler = new ExitDesktopTaskTransitionHandler(mTransitions, + mContext); + } + + @Test + public void testTransitExitDesktopModeAnimation() throws Throwable { + final int transitionType = Transitions.TRANSIT_EXIT_DESKTOP_MODE; + final int taskId = 1; + WindowContainerTransaction wct = new WindowContainerTransaction(); + doReturn(mToken).when(mTransitions) + .startTransition(transitionType, wct, mExitDesktopTaskTransitionHandler); + + mExitDesktopTaskTransitionHandler.startTransition(transitionType, wct); + + TransitionInfo.Change change = + createChange(WindowManager.TRANSIT_CHANGE, taskId, WINDOWING_MODE_FULLSCREEN); + TransitionInfo info = createTransitionInfo(Transitions.TRANSIT_EXIT_DESKTOP_MODE, change); + ArrayList<Exception> exceptions = new ArrayList<>(); + runOnUiThread(() -> { + try { + assertTrue(mExitDesktopTaskTransitionHandler + .startAnimation(mToken, info, mStartT, mFinishT, + mTransitionFinishCallback)); + } catch (Exception e) { + exceptions.add(e); + } + }); + if (!exceptions.isEmpty()) { + throw exceptions.get(0); + } + } + + private TransitionInfo.Change createChange(@WindowManager.TransitionType int type, int taskId, + @WindowConfiguration.WindowingMode int windowingMode) { + final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); + taskInfo.taskId = taskId; + taskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); + taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); + SurfaceControl.Builder b = new SurfaceControl.Builder() + .setName("test task"); + final TransitionInfo.Change change = new TransitionInfo.Change( + taskInfo.token, b.build()); + change.setMode(type); + change.setTaskInfo(taskInfo); + return change; + } + + private static TransitionInfo createTransitionInfo( + @WindowManager.TransitionType int type, @NonNull TransitionInfo.Change change) { + TransitionInfo info = new TransitionInfo(type, 0); + info.addChange(change); + return info; + } + +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java index 5b62a940c074..ada3455fae18 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java @@ -159,7 +159,7 @@ public class PipResizeGestureHandlerTest extends ShellTestCase { mPipResizeGestureHandler.onPinchResize(upEvent); verify(mPipTaskOrganizer, times(1)) - .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any()); + .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any(), any()); assertTrue("The new size should be bigger than the original PiP size.", mPipResizeGestureHandler.getLastResizeBounds().width() @@ -198,7 +198,7 @@ public class PipResizeGestureHandlerTest extends ShellTestCase { mPipResizeGestureHandler.onPinchResize(upEvent); verify(mPipTaskOrganizer, times(1)) - .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any()); + .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any(), any()); assertTrue("The new size should be smaller than the original PiP size.", mPipResizeGestureHandler.getLastResizeBounds().width() diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 1b291468d6dc..a9f311f9e9eb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -181,7 +181,7 @@ public class SplitTransitionTests extends ShellTestCase { IBinder transition = mSplitScreenTransitions.startEnterTransition( TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), - new RemoteTransition(testRemote), mStageCoordinator, null, null); + new RemoteTransition(testRemote, "Test"), mStageCoordinator, null, null); mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface()); boolean accepted = mStageCoordinator.startAnimation(transition, info, @@ -407,7 +407,8 @@ public class SplitTransitionTests extends ShellTestCase { TransitionInfo enterInfo = createEnterPairInfo(); IBinder enterTransit = mSplitScreenTransitions.startEnterTransition( TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), - new RemoteTransition(new TestRemoteTransition()), mStageCoordinator, null, null); + new RemoteTransition(new TestRemoteTransition(), "Test"), + mStageCoordinator, null, null); mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface()); mStageCoordinator.startAnimation(enterTransit, enterInfo, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index 60d697823f64..5cd548bfe5ab 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -277,7 +277,7 @@ public class ShellTransitionTests extends ShellTestCase { IBinder transitToken = new Binder(); transitions.requestStartTransition(transitToken, new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, - new RemoteTransition(testRemote))); + new RemoteTransition(testRemote, "Test"))); verify(mOrganizer, times(1)).startTransition(eq(transitToken), any()); TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build(); @@ -422,7 +422,7 @@ public class ShellTransitionTests extends ShellTestCase { new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()}; filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT}; - transitions.registerRemote(filter, new RemoteTransition(testRemote)); + transitions.registerRemote(filter, new RemoteTransition(testRemote, "Test")); mMainExecutor.flushAll(); IBinder transitToken = new Binder(); @@ -466,11 +466,12 @@ public class ShellTransitionTests extends ShellTestCase { final int transitType = TRANSIT_FIRST_CUSTOM + 1; OneShotRemoteHandler oneShot = new OneShotRemoteHandler(mMainExecutor, - new RemoteTransition(testRemote)); + new RemoteTransition(testRemote, "Test")); // Verify that it responds to the remote but not other things. IBinder transitToken = new Binder(); assertNotNull(oneShot.handleRequest(transitToken, - new TransitionRequestInfo(transitType, null, new RemoteTransition(testRemote)))); + new TransitionRequestInfo(transitType, null, + new RemoteTransition(testRemote, "Test")))); assertNull(oneShot.handleRequest(transitToken, new TransitionRequestInfo(transitType, null, null))); diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 3b129720c727..5d79104200d9 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -738,6 +738,9 @@ cc_test { "tests/unit/VectorDrawableTests.cpp", "tests/unit/WebViewFunctorManagerTests.cpp", ], + data: [ + ":hwuimicro", + ], } // ------------------------ diff --git a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp index 768dfcd52840..706f18c3be80 100644 --- a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp @@ -85,28 +85,20 @@ static void HardwareBufferRenderer_destroy(jlong renderProxy) { } static SkMatrix createMatrixFromBufferTransform(SkScalar width, SkScalar height, int transform) { - auto matrix = SkMatrix(); switch (transform) { case ANATIVEWINDOW_TRANSFORM_ROTATE_90: - matrix.setRotate(90); - matrix.postTranslate(width, 0); - break; + return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1); case ANATIVEWINDOW_TRANSFORM_ROTATE_180: - matrix.setRotate(180); - matrix.postTranslate(width, height); - break; + return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1); case ANATIVEWINDOW_TRANSFORM_ROTATE_270: - matrix.setRotate(270); - matrix.postTranslate(0, width); - break; + return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1); default: ALOGE("Invalid transform provided. Transform should be validated from" "the java side. Leveraging identity transform as a fallback"); [[fallthrough]]; case ANATIVEWINDOW_TRANSFORM_IDENTITY: - break; + return SkMatrix::I(); } - return matrix; } static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, jlong renderProxy, @@ -117,8 +109,8 @@ static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, auto skHeight = static_cast<SkScalar>(height); auto matrix = createMatrixFromBufferTransform(skWidth, skHeight, transform); auto colorSpace = GraphicsJNI::getNativeColorSpace(colorspacePtr); - proxy->setHardwareBufferRenderParams( - HardwareBufferRenderParams(matrix, colorSpace, createRenderCallback(env, consumer))); + proxy->setHardwareBufferRenderParams(HardwareBufferRenderParams( + width, height, matrix, colorSpace, createRenderCallback(env, consumer))); nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC); UiFrameInfoBuilder(proxy->frameInfo()) .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID, diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index 202a62cf320c..cc987bcd8f0e 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -69,15 +69,9 @@ MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() { } Frame SkiaOpenGLPipeline::getFrame() { - if (mHardwareBuffer) { - AHardwareBuffer_Desc description; - AHardwareBuffer_describe(mHardwareBuffer, &description); - return Frame(description.width, description.height, 0); - } else { - LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, - "drawRenderNode called on a context with no surface!"); - return mEglManager.beginFrame(mEglSurface); - } + LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, + "drawRenderNode called on a context with no surface!"); + return mEglManager.beginFrame(mEglSurface); } IRenderPipeline::DrawResult SkiaOpenGLPipeline::draw( diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 99298bc0fe9b..c8f2e69ae0a4 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -66,15 +66,8 @@ MakeCurrentResult SkiaVulkanPipeline::makeCurrent() { } Frame SkiaVulkanPipeline::getFrame() { - if (mHardwareBuffer) { - AHardwareBuffer_Desc description; - AHardwareBuffer_describe(mHardwareBuffer, &description); - return Frame(description.width, description.height, 0); - } else { - LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, - "getFrame() called on a context with no surface!"); - return vulkanManager().dequeueNextBuffer(mVkSurface); - } + LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!"); + return vulkanManager().dequeueNextBuffer(mVkSurface); } IRenderPipeline::DrawResult SkiaVulkanPipeline::draw( diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index dd781bb85470..6b2c99534a4c 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -528,6 +528,14 @@ void CanvasContext::notifyFramePending() { sendLoadResetHint(); } +Frame CanvasContext::getFrame() { + if (mHardwareBuffer != nullptr) { + return {mBufferParams.getLogicalWidth(), mBufferParams.getLogicalHeight(), 0}; + } else { + return mRenderPipeline->getFrame(); + } +} + void CanvasContext::draw() { if (auto grContext = getGrContext()) { if (grContext->abandoned()) { @@ -569,7 +577,8 @@ void CanvasContext::draw() { mCurrentFrameInfo->markIssueDrawCommandsStart(); - Frame frame = mRenderPipeline->getFrame(); + Frame frame = getFrame(); + SkRect windowDirty = computeDirtyRect(frame, &dirty); ATRACE_FORMAT("Drawing " RECT_STRING, SK_RECT_ARGS(dirty)); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index b26c018e86fb..3f2533959c20 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -264,6 +264,8 @@ private: FrameInfo* getFrameInfoFromLast4(uint64_t frameNumber, uint32_t surfaceControlId); + Frame getFrame(); + // The same type as Frame.mWidth and Frame.mHeight int32_t mLastFrameWidth = 0; int32_t mLastFrameHeight = 0; diff --git a/libs/hwui/renderthread/HardwareBufferRenderParams.h b/libs/hwui/renderthread/HardwareBufferRenderParams.h index 91fe3f6cf273..8c942d0fa102 100644 --- a/libs/hwui/renderthread/HardwareBufferRenderParams.h +++ b/libs/hwui/renderthread/HardwareBufferRenderParams.h @@ -36,9 +36,12 @@ class RenderProxy; class HardwareBufferRenderParams { public: HardwareBufferRenderParams() = default; - HardwareBufferRenderParams(const SkMatrix& transform, const sk_sp<SkColorSpace>& colorSpace, + HardwareBufferRenderParams(int32_t logicalWidth, int32_t logicalHeight, + const SkMatrix& transform, const sk_sp<SkColorSpace>& colorSpace, RenderCallback&& callback) - : mTransform(transform) + : mLogicalWidth(logicalWidth) + , mLogicalHeight(logicalHeight) + , mTransform(transform) , mColorSpace(colorSpace) , mRenderCallback(std::move(callback)) {} const SkMatrix& getTransform() const { return mTransform; } @@ -50,7 +53,12 @@ public: } } + int32_t getLogicalWidth() { return mLogicalWidth; } + int32_t getLogicalHeight() { return mLogicalHeight; } + private: + int32_t mLogicalWidth; + int32_t mLogicalHeight; SkMatrix mTransform = SkMatrix::I(); sk_sp<SkColorSpace> mColorSpace = SkColorSpace::MakeSRGB(); RenderCallback mRenderCallback = nullptr; |