diff options
15 files changed, 496 insertions, 24 deletions
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 5276d9d6a4df..55e90e74a404 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 @@ -324,6 +324,8 @@ public class PipAnimationController { private final @AnimationType int mAnimationType; private final Rect mDestinationBounds = new Rect(); + private final Point mLeashOffset = new Point(); + private T mBaseValue; protected T mCurrentValue; protected T mStartValue; @@ -338,13 +340,22 @@ public class PipAnimationController { // Flag to avoid double-end private boolean mHasRequestedEnd; - private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash, - @AnimationType int animationType, - Rect destinationBounds, T baseValue, T startValue, T endValue) { + private PipTransitionAnimator(@NonNull TaskInfo taskInfo, @NonNull SurfaceControl leash, + @AnimationType int animationType, @NonNull Rect destinationBounds, + @NonNull T baseValue, @NonNull T startValue, @NonNull T endValue) { + this(taskInfo, leash, animationType, destinationBounds, new Point(), baseValue, + startValue, endValue); + } + + private PipTransitionAnimator(@NonNull TaskInfo taskInfo, @NonNull SurfaceControl leash, + @AnimationType int animationType, @NonNull Rect destinationBounds, + @NonNull Point leashOffset, @NonNull T baseValue, @NonNull T startValue, + @NonNull T endValue) { mTaskInfo = taskInfo; mLeash = leash; mAnimationType = animationType; mDestinationBounds.set(destinationBounds); + mLeashOffset.set(leashOffset); mBaseValue = baseValue; mStartValue = startValue; mEndValue = endValue; @@ -496,6 +507,15 @@ public class PipAnimationController { } } + /** + * Returns the offset of the {@link #mLeash}. + */ + @NonNull + Point getLeashOffset() { + // Use copy to prevent the leash to be modified unexpectedly. + return new Point(mLeashOffset); + } + void setCurrentValue(T value) { mCurrentValue = value; } @@ -692,8 +712,8 @@ public class PipAnimationController { final Rect zeroInsets = new Rect(0, 0, 0, 0); // construct new Rect instances in case they are recycled - return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, - endBounds, new Rect(baseBounds), new Rect(startBounds), new Rect(endBounds)) { + return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, endBounds, + leashOffset, new Rect(baseBounds), new Rect(startBounds), new Rect(endBounds)) { private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect()); private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect()); @@ -720,6 +740,7 @@ public class PipAnimationController { // Use the bounds relative to the task leash in case the leash does not // start from (0, 0). final Rect relativeEndBounds = new Rect(end); + final Point leashOffset = getLeashOffset(); relativeEndBounds.offset(-leashOffset.x, -leashOffset.y); getSurfaceTransactionHelper() .crop(tx, leash, relativeEndBounds) 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 72c1ef06806a..0042ec954f32 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 @@ -507,8 +507,8 @@ public class PipTransition extends PipTransitionController { } @Override - public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, - @PipAnimationController.TransitionDirection int direction, + public void onFinishResize(@NonNull TaskInfo taskInfo, @NonNull Rect destinationBounds, + @NonNull Point leashOffset, @PipAnimationController.TransitionDirection int direction, @NonNull SurfaceControl.Transaction tx) { final boolean enteringPip = isInPipDirection(direction); if (enteringPip) { @@ -531,12 +531,16 @@ public class PipTransition extends PipTransitionController { if (mFixedRotationState != FIXED_ROTATION_TRANSITION && mFinishTransaction != null) { mFinishTransaction.merge(tx); - // Set window crop and position to destination bounds to avoid flickering. + // Set crop and position to destination bounds to avoid flickering. if (hasValidLeash) { - mFinishTransaction.setWindowCrop(leash, destinationBounds.width(), - destinationBounds.height()); - mFinishTransaction.setPosition(leash, destinationBounds.left, - destinationBounds.top); + final Rect relativeDestinationBounds = new Rect(destinationBounds); + relativeDestinationBounds.offset(-leashOffset.x, -leashOffset.y); + mFinishTransaction + .setCrop(leash, relativeDestinationBounds) + // Note that we should set the position to the start position of + // leash then the visible region will be at the same place even if + // the crop region doesn't start at (0, 0). + .setPosition(leash, leashOffset.x, leashOffset.y); } } } else { @@ -1267,7 +1271,8 @@ public class PipTransition extends PipTransitionController { mPipBoundsState.setBounds(destinationBounds); final SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); - onFinishResize(pipTaskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx); + onFinishResize(pipTaskInfo, destinationBounds, animator.getLeashOffset(), + TRANSITION_DIRECTION_TO_PIP, tx); sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); if (swipePipToHomeOverlay != null) { mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index a273822759f6..6129651dc271 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -31,6 +31,7 @@ import android.app.PictureInPictureUiState; import android.app.TaskInfo; import android.content.ComponentName; import android.content.pm.ActivityInfo; +import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; @@ -92,7 +93,8 @@ public abstract class PipTransitionController implements Transitions.TransitionH mPipOrganizer.fadeOutAndRemoveOverlay(mPipOrganizer.mPipOverlay, null /* callback */, true /* withStartDelay*/); } - onFinishResize(taskInfo, animator.getDestinationBounds(), direction, tx); + onFinishResize(taskInfo, animator.getDestinationBounds(), + animator.getLeashOffset(), direction, tx); sendOnPipTransitionFinished(direction); } @@ -112,9 +114,9 @@ public abstract class PipTransitionController implements Transitions.TransitionH * Called when transition is about to finish. This is usually for performing tasks such as * applying WindowContainerTransaction to finalize the PiP bounds and send to the framework. */ - public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, - @PipAnimationController.TransitionDirection int direction, - SurfaceControl.Transaction tx) { + public void onFinishResize(@NonNull TaskInfo taskInfo, @NonNull Rect destinationBounds, + @NonNull Point leashOffset, @PipAnimationController.TransitionDirection int direction, + @NonNull SurfaceControl.Transaction tx) { } /** diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp index ddbc681f7cac..f40edaebec5e 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp @@ -266,5 +266,26 @@ test_module_config { test_suites: ["device-tests"], } +test_module_config { + name: "WMShellFlickerTestsPip-nonMatchParent", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.*"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-BottomHalfExitPipToAppViaExpandButtonTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaExpandButtonTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-BottomHalfExitPipToAppViaIntentTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaIntentTest"], + test_suites: ["device-tests"], +} + // End breakdowns for WMShellFlickerTestsPip module //////////////////////////////////////////////////////////////////////////////// diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt index c37bf3579e93..7861d201cd29 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt @@ -40,7 +40,6 @@ abstract class PipTransition(flicker: LegacyFlickerTest) : BaseTest(flicker) { @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() - protected val pipApp = PipAppHelper(instrumentation) protected val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation) protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation) @@ -63,6 +62,11 @@ abstract class PipTransition(flicker: LegacyFlickerTest) : BaseTest(flicker) { } } + /** + * Defines the test app to run PIP flicker test. + */ + protected open val pipApp = PipAppHelper(instrumentation) + /** Defines the transition used to run the test */ protected open val thisTransition: FlickerBuilder.() -> Unit = {} diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppTransition.kt new file mode 100644 index 000000000000..a6f29fc3452b --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppTransition.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2024 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.nonmatchparent + +import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsEnabled +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import com.android.server.wm.flicker.helpers.BottomHalfPipAppHelper +import com.android.server.wm.flicker.helpers.PipAppHelper +import com.android.window.flags.Flags +import com.android.wm.shell.flicker.pip.common.ExitPipToAppTransition +import org.junit.Test + +/** + * Base test class to verify PIP exit animation with an activity layout to the bottom half of + * the container. + */ +@RequiresFlagsEnabled(Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY) +abstract class BottomHalfExitPipToAppTransition(flicker: LegacyFlickerTest) : + ExitPipToAppTransition(flicker) { + + override val pipApp: PipAppHelper = BottomHalfPipAppHelper(instrumentation) + + @Presubmit + @Test + override fun showBothAppLayersThenHidePip() { + // Disabled since the BottomHalfPipActivity just covers half of the simple activity. + } + + @Presubmit + @Test + override fun showBothAppWindowsThenHidePip() { + // Disabled since the BottomHalfPipActivity just covers half of the simple activity. + } + + @Presubmit + @Test + override fun pipAppCoversFullScreenAtEnd() { + // Disabled since the BottomHalfPipActivity just covers half of the simple activity. + } + + /** + * Checks that the [testApp] and [pipApp] are always visible since the [pipApp] only covers + * half of screen. + */ + @Presubmit + @Test + fun showBothAppLayersDuringPipTransition() { + flicker.assertLayers { + isVisible(testApp) + .isVisible(pipApp.or(ComponentNameMatcher.TRANSITION_SNAPSHOT)) + } + } + + /** + * Checks that the [testApp] and [pipApp] are always visible since the [pipApp] only covers + * half of screen. + */ + @Presubmit + @Test + fun showBothAppWindowsDuringPipTransition() { + flicker.assertWm { + isAppWindowVisible(testApp) + .isAppWindowOnTop(pipApp) + .isAppWindowVisible(pipApp) + } + } + + /** + * Verify that the [testApp] and [pipApp] covers the entire screen at the end of PIP exit + * animation since the [pipApp] will use a bottom half layout. + */ + @Presubmit + @Test + fun testPlusPipAppCoversWindowFrameAtEnd() { + flicker.assertLayersEnd { + val pipRegion = visibleRegion(pipApp).region + visibleRegion(testApp).plus(pipRegion).coversExactly(displayBounds) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaExpandButtonTest.kt new file mode 100644 index 000000000000..f492bd444702 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaExpandButtonTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 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.nonmatchparent + +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test expanding a pip window back to bottom half layout via the expand button + * + * To run this test: `atest WMShellFlickerTestsPip:BottomHalfExitPipToAppViaExpandButtonTest` + * + * Actions: + * ``` + * Launch an app in pip mode [bottomHalfPipApp], + * Launch another full screen mode [testApp] + * Expand [bottomHalfPipApp] app to bottom half layout 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) + * are inherited [PipTransition] + * 2. Part of the test setup occurs automatically via + * [android.tools.flicker.legacy.runner.TransitionRunner], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + * ``` + */ +@RunWith(Parameterized::class) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class BottomHalfExitPipToAppViaExpandButtonTest(flicker: LegacyFlickerTest) : + BottomHalfExitPipToAppTransition(flicker) +{ + override val thisTransition: FlickerBuilder.() -> Unit = { + setup { + // launch an app behind the pip one + testApp.launchViaIntent(wmHelper) + } + transitions { + // This will bring PipApp to fullscreen + pipApp.expandPipWindowToApp(wmHelper) + // Wait until the transition idle and test and pip app still shows. + wmHelper.StateSyncBuilder().withLayerVisible(testApp).withLayerVisible(pipApp) + .withAppTransitionIdle().waitForAndVerify() + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt new file mode 100644 index 000000000000..a76a647348a1 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024 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.nonmatchparent + +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test expanding a pip window back to bottom half layout via an intent + * + * To run this test: `atest WMShellFlickerTestsPip:BottomHalfExitPipToAppViaIntentTest` + * + * Actions: + * ``` + * Launch an app in pip mode [bottomHalfPipApp], + * Launch another full screen mode [testApp] + * Expand [bottomHalfPipApp] app to bottom half layout via an intent + * ``` + * + * Notes: + * ``` + * 1. Some default assertions (e.g., nav bar, status bar and screen covered) + * are inherited from [PipTransition] + * 2. Part of the test setup occurs automatically via + * [android.tools.flicker.legacy.runner.TransitionRunner], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + * ``` + */ +@RunWith(Parameterized::class) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class BottomHalfExitPipToAppViaIntentTest(flicker: LegacyFlickerTest) : + BottomHalfExitPipToAppTransition(flicker) +{ + override val thisTransition: FlickerBuilder.() -> Unit = { + setup { + // launch an app behind the pip one + testApp.launchViaIntent(wmHelper) + } + transitions { + // This will bring PipApp to fullscreen + pipApp.exitPipToFullScreenViaIntent(wmHelper) + // Wait until the transition idle and test and pip app still shows. + wmHelper.StateSyncBuilder().withLayerVisible(testApp).withLayerVisible(pipApp) + .withAppTransitionIdle().waitForAndVerify() + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt new file mode 100644 index 000000000000..6573c2c83f20 --- /dev/null +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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.server.wm.flicker.helpers + +import android.app.Instrumentation +import android.content.Intent +import android.tools.traces.parsers.toFlickerComponent +import com.android.server.wm.flicker.testapp.ActivityOptions + +class BottomHalfPipAppHelper( + instrumentation: Instrumentation, + private val useLaunchingActivity: Boolean = false, +) : PipAppHelper( + instrumentation, + appName = ActivityOptions.BottomHalfPip.LABEL, + componentNameMatcher = ActivityOptions.BottomHalfPip.COMPONENT + .toFlickerComponent() +) { + override val openAppIntent: Intent + get() = super.openAppIntent.apply { + component = if (useLaunchingActivity) { + ActivityOptions.BottomHalfPip.LAUNCHING_APP_COMPONENT + } else { + ActivityOptions.BottomHalfPip.COMPONENT + } + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index db4838ee6092..2fe84b00b040 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -27,6 +27,7 @@ import android.tools.device.apphelpers.StandardAppHelper import android.tools.helpers.FIND_TIMEOUT import android.tools.helpers.SYSTEMUI_PACKAGE import android.tools.traces.ConditionsFactory +import android.tools.traces.component.ComponentNameMatcher import android.tools.traces.component.IComponentMatcher import android.tools.traces.parsers.WindowManagerStateHelper import android.tools.traces.parsers.toFlickerComponent @@ -35,12 +36,11 @@ import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.testapp.ActivityOptions -open class PipAppHelper(instrumentation: Instrumentation) : - StandardAppHelper( - instrumentation, - ActivityOptions.Pip.LABEL, - ActivityOptions.Pip.COMPONENT.toFlickerComponent() - ) { +open class PipAppHelper( + instrumentation: Instrumentation, + appName: String = ActivityOptions.Pip.LABEL, + componentNameMatcher: ComponentNameMatcher = ActivityOptions.Pip.COMPONENT.toFlickerComponent(), +) : StandardAppHelper(instrumentation, appName, componentNameMatcher) { private val mediaSessionManager: MediaSessionManager get() = context.getSystemService(MediaSessionManager::class.java) diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml index 9ce8e807f612..7c24a4adca3d 100644 --- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml @@ -347,6 +347,27 @@ <category android:name="android.intent.category.LEANBACK_LAUNCHER"/> </intent-filter> </activity> + <activity android:name=".BottomHalfPipLaunchingActivity" + android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" + android:taskAffinity="com.android.server.wm.flicker.testapp.BottomHalfPipLaunchingActivity" + android:theme="@style/CutoutShortEdges" + android:label="BottomHalfPipLaunchingActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <activity + android:name=".BottomHalfPipActivity" + android:resizeableActivity="true" + android:supportsPictureInPicture="true" + android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" + android:taskAffinity="com.android.server.wm.flicker.testapp.BottomHalfPipLaunchingActivity" + android:theme="@style/TranslucentTheme" + android:label="BottomHalfPipActivity" + android:exported="true"> + </activity> <activity android:name=".SplitScreenActivity" android:resizeableActivity="true" android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenActivity" diff --git a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml index 47d113717ae0..837d050b73ff 100644 --- a/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml +++ b/tests/FlickerTests/test-apps/flickerapp/res/values/styles.xml @@ -62,6 +62,12 @@ <item name="android:backgroundDimEnabled">false</item> </style> + <style name="TranslucentTheme" parent="@style/OptOutEdgeToEdge"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowContentOverlay">@null</item> + <item name="android:backgroundDimEnabled">false</item> + </style> + <style name="no_starting_window" parent="@style/OptOutEdgeToEdge"> <item name="android:windowDisablePreview">true</item> </style> diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java index 73625da9dfa5..0c1ac9951d32 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java @@ -241,6 +241,21 @@ public class ActivityOptions { FLICKER_APP_PACKAGE + ".PipActivity"); } + public static class BottomHalfPip { + public static final String LAUNCHING_APP_LABEL = "BottomHalfPipLaunchingActivity"; + // Test App > Bottom Half PIP Activity + public static final String LABEL = "BottomHalfPipActivity"; + + // Use the bottom half layout for PIP Activity + public static final String EXTRA_BOTTOM_HALF_LAYOUT = "bottom_half"; + + public static final ComponentName LAUNCHING_APP_COMPONENT = new ComponentName( + FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".BottomHalfPipLaunchingActivity"); + + public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE, + FLICKER_APP_PACKAGE + ".BottomHalfPipActivity"); + } + public static class SplitScreen { public static class Primary { public static final String LABEL = "SplitScreenPrimaryActivity"; diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipActivity.java new file mode 100644 index 000000000000..3d4865572486 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipActivity.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2024 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.server.wm.flicker.testapp; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.ViewGroup.LayoutParams; +import android.view.WindowManager; + +import androidx.annotation.NonNull; + +public class BottomHalfPipActivity extends PipActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTheme(R.style.TranslucentTheme); + updateLayout(); + } + + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + updateLayout(); + } + + /** + * Sets to match parent layout if the activity is + * {@link Activity#isInPictureInPictureMode()}. Otherwise, set to bottom half + * layout. + * + * @see #setToBottomHalfMode(boolean) + */ + private void updateLayout() { + setToBottomHalfMode(!isInPictureInPictureMode()); + } + + /** + * Sets `useBottomHalfLayout` to `true` to use the bottom half layout. Use the + * [LayoutParams.MATCH_PARENT] layout. + */ + private void setToBottomHalfMode(boolean useBottomHalfLayout) { + final WindowManager.LayoutParams attrs = getWindow().getAttributes(); + if (useBottomHalfLayout) { + final int taskHeight = getWindowManager().getCurrentWindowMetrics().getBounds() + .height(); + attrs.y = taskHeight / 2; + attrs.height = taskHeight / 2; + } else { + attrs.y = 0; + attrs.height = LayoutParams.MATCH_PARENT; + } + getWindow().setAttributes(attrs); + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java new file mode 100644 index 000000000000..d9d4361411bb --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 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.server.wm.flicker.testapp; + +import android.content.Intent; +import android.os.Bundle; + +public class BottomHalfPipLaunchingActivity extends SimpleActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Intent intent = new Intent(this, BottomHalfPipActivity.class); + startActivity(intent); + } +} |