diff --git a/libs/WindowManager/Shell/tests/README.md b/libs/WindowManager/Shell/tests/README.md
new file mode 100644
index 0000000000000..c19db76a358c8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/README.md
@@ -0,0 +1,15 @@
+# WM Shell Test
+
+This contains all tests written for WM (WindowManager) Shell and it's currently
+divided into 3 categories
+
+- unittest, tests against individual functions, usually @SmallTest and do not
+ require UI automation nor real device to run
+- integration, this maybe a mix of functional and integration tests. Contains
+ tests verify the WM Shell as a whole, like talking to WM core. This usually
+ involves mocking the window manager service or even talking to the real one.
+ Due to this nature, test cases in this package is normally annotated as
+ @LargeTest and runs with UI automation on real device
+- flicker, similar to functional tests with its sole focus on flickerness. See
+ [WM Shell Flicker Test Package](http://cs/android/framework/base/libs/WindowManager/Shell/tests/flicker/)
+ for more details
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
new file mode 100644
index 0000000000000..5879022218263
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2020 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.
+//
+
+android_test {
+ name: "WMShellFlickerTests",
+ srcs: ["src/**/*.java", "src/**/*.kt"],
+ manifest: "AndroidManifest.xml",
+ test_config: "AndroidTest.xml",
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "flickerlib",
+ "truth-prebuilt",
+ "app-helpers-core",
+ "launcher-helper-lib",
+ "launcher-aosp-tapl"
+ ],
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
new file mode 100644
index 0000000000000..8b2f6681554a4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
new file mode 100644
index 0000000000000..526fc502c0fbd
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/WindowManager/Shell/tests/flicker/README.md b/libs/WindowManager/Shell/tests/flicker/README.md
new file mode 100644
index 0000000000000..4502d498a65b9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/README.md
@@ -0,0 +1,10 @@
+# WM Shell Flicker Test Package
+
+Please reference the following links
+
+- [Introduction to Flicker Test Library](http://cs/android/platform_testing/libraries/flicker/)
+- [Flicker Test in frameworks/base](http://cs/android/frameworks/base/tests/FlickerTests/)
+
+on what is Flicker Test and how to write a Flicker Test
+
+To run the Flicker Tests for WM Shell, simply run `atest WMShellFlickerTests`
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
new file mode 100644
index 0000000000000..4ff2bfca3a4ae
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 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
+
+import com.android.server.wm.flicker.dsl.EventLogAssertion
+import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.dsl.WmAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
+
+@JvmOverloads
+fun WmAssertion.statusBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun WmAssertion.navBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.noUncoveredRegions(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ allStates: Boolean = true,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
+ val endingBounds = WindowUtils.getDisplayBounds(endRotation)
+ if (allStates) {
+ all("noUncoveredRegions", enabled, bugId) {
+ if (startingBounds == endingBounds) {
+ this.coversAtLeastRegion(startingBounds)
+ } else {
+ this.coversAtLeastRegion(startingBounds)
+ .then()
+ .coversAtLeastRegion(endingBounds)
+ }
+ }
+ } else {
+ start("noUncoveredRegions_StartingPos") {
+ this.coversAtLeastRegion(startingBounds)
+ }
+ end("noUncoveredRegions_EndingPos") {
+ this.coversAtLeastRegion(endingBounds)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerRotatesAndScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
+ val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
+
+ start("navBarLayerRotatesAndScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("navBarLayerRotatesAndScales_EndingPost", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, endingPos)
+ }
+
+ if (startingPos == endingPos) {
+ all("navBarLayerRotatesAndScales", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerRotatesScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
+ val endingPos = WindowUtils.getStatusBarPosition(endRotation)
+
+ start("statusBarLayerRotatesScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("statusBarLayerRotatesScales_EndingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, endingPos)
+ }
+}
+
+fun EventLogAssertion.focusChanges(
+ vararg windows: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusChanges(windows)
+ }
+}
+
+fun EventLogAssertion.focusDoesNotChange(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusDoesNotChange()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
new file mode 100644
index 0000000000000..99f824bb83419
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 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
+
+import android.os.RemoteException
+import android.os.SystemClock
+import android.platform.helpers.IAppHelper
+import android.view.Surface
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.server.wm.flicker.Flicker
+
+/**
+ * Base class of all Flicker test that performs common functions for all flicker tests:
+ *
+ *
+ * - Caches transitions so that a transition is run once and the transition results are used by
+ * tests multiple times. This is needed for parameterized tests which call the BeforeClass methods
+ * multiple times.
+ * - Keeps track of all test artifacts and deletes ones which do not need to be reviewed.
+ * - Fails tests if results are not available for any test due to jank.
+ */
+abstract class FlickerTestBase {
+ val instrumentation by lazy {
+ InstrumentationRegistry.getInstrumentation()
+ }
+ val uiDevice by lazy {
+ UiDevice.getInstance(instrumentation)
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param rotation Initial screen rotation
+ *
+ * @return test tag with pattern ____
+ */
+ protected fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
+ return buildTestTag(
+ testName, app, rotation, rotation, app2 = null, extraInfo = "")
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ *
+ * @return test tag with pattern ____-
+ */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int
+ ): String {
+ return buildTestTag(
+ testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param app2 Second app being launched (if any)
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ * @param extraInfo Additional information to append to the tag
+ *
+ * @return test tag with pattern __(S)>__(S)>[__]
+ */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int,
+ app2: IAppHelper?,
+ extraInfo: String
+ ): String {
+ var testTag = "${testName}__${app.launcherName}"
+ if (app2 != null) {
+ testTag += "-${app2.launcherName}"
+ }
+ testTag += "__${Surface.rotationToString(beginRotation)}"
+ if (endRotation != beginRotation) {
+ testTag += "-${Surface.rotationToString(endRotation)}"
+ }
+ if (extraInfo.isNotEmpty()) {
+ testTag += "__$extraInfo"
+ }
+ return testTag
+ }
+
+ protected fun Flicker.setRotation(rotation: Int) {
+ try {
+ when (rotation) {
+ Surface.ROTATION_270 -> device.setOrientationLeft()
+ Surface.ROTATION_90 -> device.setOrientationRight()
+ Surface.ROTATION_0 -> device.setOrientationNatural()
+ else -> device.setOrientationNatural()
+ }
+ // Wait for animation to complete
+ SystemClock.sleep(1000)
+ } catch (e: RemoteException) {
+ throw RuntimeException(e)
+ }
+ }
+
+ companion object {
+ const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
+ const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
+ const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
new file mode 100644
index 0000000000000..90334ae91e9d3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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
+
+import android.view.Surface
+import org.junit.runners.Parameterized
+
+abstract class NonRotationTestBase(
+ protected val rotationName: String,
+ protected val rotation: Int
+) : FlickerTestBase() {
+ companion object {
+ const val SCREENSHOT_LAYER = "RotationLayer"
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
new file mode 100644
index 0000000000000..308a36efef876
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.helpers
+
+import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import com.android.server.wm.flicker.StandardAppHelper
+
+abstract class FlickerAppHelper(
+ instr: Instrumentation,
+ launcherName: String,
+ launcherStrategy: ILauncherStrategy
+) : StandardAppHelper(instr, sFlickerPackage, launcherName, launcherStrategy) {
+ companion object {
+ var sFlickerPackage = "com.android.wm.shell.flicker.testapp"
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
new file mode 100644
index 0000000000000..539170202b8ad
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.helpers
+
+import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import android.support.test.launcherhelper.LauncherStrategyFactory
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.closePipWindow
+import org.junit.Assert
+
+class PipAppHelper(
+ instr: Instrumentation,
+ launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
+ .getInstance(instr)
+ .launcherStrategy
+) : FlickerAppHelper(instr, "PipApp", launcherStrategy) {
+ fun clickEnterPipButton(device: UiDevice) {
+ val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"))
+ Assert.assertNotNull("Pip button not found, this usually happens when the device " +
+ "was left in an unknown state (e.g. in split screen)", enterPipButton)
+ enterPipButton.click()
+ device.hasPipWindow()
+ }
+
+ fun closePipWindow(device: UiDevice) {
+ device.closePipWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
new file mode 100644
index 0000000000000..4b04449bdbc2b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 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.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.LargeTest
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.expandPipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible
+import com.android.wm.shell.flicker.navBarLayerRotatesAndScales
+import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.noUncoveredRegions
+import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible
+import com.android.wm.shell.flicker.statusBarLayerRotatesScales
+import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest FlickerTests:PipToAppTest`
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 152738416)
+class EnterPipTest(
+ rotationName: String,
+ rotation: Int
+) : PipTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("enterPip", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ device.pressHome()
+ testApp.open()
+ this.setRotation(rotation)
+ }
+ }
+ teardown {
+ eachRun {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ }
+ }
+ transitions {
+ testApp.clickEnterPipButton(device)
+ device.expandPipWindow()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ all("pipWindowBecomesVisible") {
+ this.showsAppWindow(testApp.`package`)
+ .then()
+ .showsAppWindow(sPipWindowTitle)
+ }
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation, Surface.ROTATION_0)
+ statusBarLayerRotatesScales(rotation, Surface.ROTATION_0)
+
+ all("pipLayerBecomesVisible") {
+ this.showsLayer(testApp.launcherName)
+ .then()
+ .showsLayer(sPipWindowTitle)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
similarity index 60%
rename from libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
index f1ead3c8a4419..3822d69a65f50 100644
--- a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
@@ -14,25 +14,18 @@
* limitations under the License.
*/
-package com.android.wm.shell;
+package com.android.wm.shell.flicker.pip
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
+import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.helpers.PipAppHelper
-import org.junit.Test;
-import org.junit.runner.RunWith;
+abstract class PipTestBase(
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ protected val testApp = PipAppHelper(instrumentation)
-/**
- * Tests for the shell.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class WindowManagerShellTest {
-
- WindowManagerShell mShell;
-
- @Test
- public void testNothing() {
- // Do nothing
+ companion object {
+ const val sPipWindowTitle = "PipMenuActivity"
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
new file mode 100644
index 0000000000000..d12b492452774
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2020 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.
+
+android_test {
+ name: "WMShellFlickerTestApp",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
new file mode 100644
index 0000000000000..95dc1d48eee8e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
new file mode 100644
index 0000000000000..e1870d9c523de
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java
new file mode 100644
index 0000000000000..305281691e119
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.testapp;
+
+import android.app.Activity;
+import android.app.PictureInPictureParams;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Rational;
+import android.view.WindowManager;
+import android.widget.Button;
+
+public class PipActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ WindowManager.LayoutParams p = getWindow().getAttributes();
+ p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+ .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ getWindow().setAttributes(p);
+ setContentView(R.layout.activity_pip);
+ Button enterPip = (Button) findViewById(R.id.enter_pip);
+
+ PictureInPictureParams params = new PictureInPictureParams.Builder()
+ .setAspectRatio(new Rational(1, 1))
+ .setSourceRectHint(new Rect(0, 0, 100, 100))
+ .build();
+
+ enterPip.setOnClickListener((v) -> enterPictureInPictureMode(params));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
similarity index 96%
rename from libs/WindowManager/Shell/tests/Android.bp
rename to libs/WindowManager/Shell/tests/unittest/Android.bp
index 9868879cebb90..692e2fa88fc3a 100644
--- a/libs/WindowManager/Shell/tests/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test {
- name: "WindowManagerShellTests",
+ name: "WMShellUnitTests",
srcs: ["**/*.java"],
diff --git a/libs/WindowManager/Shell/tests/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
similarity index 100%
rename from libs/WindowManager/Shell/tests/AndroidManifest.xml
rename to libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
diff --git a/libs/WindowManager/Shell/tests/AndroidTest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidTest.xml
similarity index 90%
rename from libs/WindowManager/Shell/tests/AndroidTest.xml
rename to libs/WindowManager/Shell/tests/unittest/AndroidTest.xml
index 4dce4db360e4c..21ed2c075dff7 100644
--- a/libs/WindowManager/Shell/tests/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidTest.xml
@@ -17,12 +17,12 @@
-
+
-
+
diff --git a/libs/WindowManager/Shell/tests/res/values/config.xml b/libs/WindowManager/Shell/tests/unittest/res/values/config.xml
similarity index 100%
rename from libs/WindowManager/Shell/tests/res/values/config.xml
rename to libs/WindowManager/Shell/tests/unittest/res/values/config.xml
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
similarity index 100%
rename from libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
similarity index 100%
rename from libs/WindowManager/Shell/tests/src/com/android/wm/shell/common/DisplayLayoutTest.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java