Merge changes from topic "bottom_half_exit_pip_flicker_tests" into main
* changes:
Add flicker tests to verify non-match parent on exit PIP
Fix PIP exit animation flickering on non-match parent activity
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 5276d9d..55e90e7 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 @@
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 @@
// 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 @@
}
}
+ /**
+ * 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 @@
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 @@
// 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 72c1ef0..0042ec9 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 @@
}
@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 @@
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 @@
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 a2738227..6129651 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.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 @@
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 @@
* 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 ddbc681..f40edae 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp
@@ -266,5 +266,26 @@
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 c37bf35..7861d20 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 @@
@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 @@
}
}
+ /**
+ * 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 0000000..a6f29fc
--- /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 0000000..f492bd4
--- /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 0000000..a76a647
--- /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 0000000..6573c2c
--- /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 db4838e..2fe84b0 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.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.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 9ce8e80..7c24a4a 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 47d1137..837d050 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 73625da..0c1ac99 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 @@
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 0000000..3d48655
--- /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 0000000..d9d4361
--- /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);
+ }
+}