1/ Add test apps from WM shell package into flicker

Add both apps to the same package to unify all test apps and helpers into a single reusable place

Test: atest FlickerLibTest && atest FlickerTests
Change-Id: I9fa18eb31b50c4e6869352250be0c89a9acb0be8
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 725963b..6e935d1 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -15,41 +15,41 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.server.wm.flicker.testapp">
+          package="com.android.server.wm.flicker.testapp">
 
     <uses-sdk android:minSdkVersion="29"
-         android:targetSdkVersion="29"/>
+              android:targetSdkVersion="29"/>
     <application android:allowBackup="false"
-         android:supportsRtl="true">
+                 android:supportsRtl="true">
         <uses-library android:name="androidx.window.extensions" android:required="false"/>
 
         <activity android:name=".SimpleActivity"
-             android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
-             android:theme="@style/CutoutShortEdges"
-             android:label="SimpleApp"
-             android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="SimpleActivity"
+                  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=".ImeActivity"
-             android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
-             android:theme="@style/CutoutShortEdges"
-             android:label="ImeApp"
-             android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="ImeActivity"
+                  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=".ImeActivityAutoFocus"
-             android:theme="@style/CutoutShortEdges"
-             android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
-             android:windowSoftInputMode="stateVisible"
-             android:configChanges="orientation|screenSize"
-             android:label="ImeAppAutoFocus"
-             android:exported="true">
+                  android:theme="@style/CutoutShortEdges"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
+                  android:windowSoftInputMode="stateVisible"
+                  android:configChanges="orientation|screenSize"
+                  android:label="ImeAppAutoFocus"
+                  android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
@@ -66,34 +66,34 @@
             </intent-filter>
         </activity>
         <activity android:name=".SeamlessRotationActivity"
-             android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
-             android:theme="@style/CutoutShortEdges"
-             android:configChanges="orientation|screenSize"
-             android:label="SeamlessApp"
-             android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:configChanges="orientation|screenSize"
+                  android:label="SeamlessActivity"
+                  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=".NonResizeableActivity"
-            android:theme="@style/CutoutShortEdges"
-            android:resizeableActivity="false"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
-            android:label="NonResizeableApp"
-            android:exported="true"
-            android:showOnLockScreen="true">
+                  android:theme="@style/CutoutShortEdges"
+                  android:resizeableActivity="false"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
+                  android:label="NonResizeableActivity"
+                  android:exported="true"
+                  android:showOnLockScreen="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
-        <activity android:name=".ButtonActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.ButtonActivity"
-            android:theme="@style/CutoutShortEdges"
-            android:configChanges="orientation|screenSize"
-            android:label="ButtonActivity"
-            android:exported="true">
+        <activity android:name=".LaunchNewActivity"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchNewActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:configChanges="orientation|screenSize"
+                  android:label="LaunchNewActivity"
+                  android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
@@ -111,55 +111,56 @@
             </intent-filter>
         </activity>
         <activity android:name=".DialogThemedActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.DialogThemedActivity"
-            android:configChanges="orientation|screenSize"
-            android:theme="@style/DialogTheme"
-            android:label="DialogThemedActivity"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.DialogThemedActivity"
+                  android:configChanges="orientation|screenSize"
+                  android:theme="@style/DialogTheme"
+                  android:label="DialogThemedActivity"
+                  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=".PortraitOnlyActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitOnlyActivity"
-            android:theme="@style/CutoutShortEdges"
-            android:screenOrientation="portrait"
-            android:configChanges="orientation|screenSize"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitOnlyActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:screenOrientation="portrait"
+                  android:configChanges="orientation|screenSize"
+                  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=".ImeEditorPopupDialogActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
-            android:configChanges="orientation|screenSize"
-            android:theme="@style/CutoutShortEdges"
-            android:label="ImeEditorPopupDialogActivity"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
+                  android:configChanges="orientation|screenSize"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="ImeEditorPopupDialogActivity"
+                  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=".ShowWhenLockedActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
-            android:theme="@style/CutoutShortEdges"
-            android:configChanges="orientation|screenSize"
-            android:label="ShowWhenLockedActivity"
-            android:showWhenLocked="true"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:configChanges="orientation|screenSize"
+                  android:label="ShowWhenLockedActivity"
+                  android:showWhenLocked="true"
+                  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=".NotificationActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
-            android:theme="@style/CutoutShortEdges"
-            android:configChanges="orientation|screenSize"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:configChanges="orientation|screenSize"
+                  android:label="NotificationActivity"
+                  android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
@@ -173,8 +174,8 @@
             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
         <activity
@@ -193,42 +194,110 @@
             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
             android:exported="false"/>
         <activity android:name=".MailActivity"
-            android:exported="true"
-            android:label="MailApp"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.MailActivity"
-            android:theme="@style/Theme.AppCompat.Light">
+                  android:exported="true"
+                  android:label="MailActivity"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.MailActivity"
+                  android:theme="@style/Theme.AppCompat.Light">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
         <activity android:name=".GameActivity"
-            android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity"
-            android:immersive="true"
-            android:theme="@android:style/Theme.NoTitleBar"
-            android:configChanges="screenSize"
-            android:label="GameApp"
-            android:exported="true">
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity"
+                  android:immersive="true"
+                  android:theme="@android:style/Theme.NoTitleBar"
+                  android:configChanges="screenSize"
+                  android:label="GameActivity"
+                  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=".PipActivity"
+                  android:resizeableActivity="true"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.PipActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:launchMode="singleTop"
+                  android:label="PipActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".SplitScreenActivity"
+                  android:resizeableActivity="true"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="SplitScreenPrimaryActivity"
+                  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=".SplitScreenSecondaryActivity"
+                  android:resizeableActivity="true"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenSecondaryActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="SplitScreenSecondaryActivity"
+                  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=".SendNotificationActivity"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SendNotificationActivity"
+                  android:theme="@style/CutoutShortEdges"
+                  android:label="SendNotificationActivity"
+                  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=".LaunchBubbleActivity"
+            android:label="LaunchBubbleActivity"
+            android:exported="true"
+            android:theme="@style/CutoutShortEdges"
+            android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".BubbleActivity"
+            android:label="BubbleActivity"
+            android:exported="false"
+            android:theme="@style/CutoutShortEdges"
+            android:resizeableActivity="true"/>
         <service
             android:name=".AssistantInteractionSessionService"
             android:exported="true"
-            android:permission="android.permission.BIND_VOICE_INTERACTION" />
+            android:permission="android.permission.BIND_VOICE_INTERACTION"/>
         <service
             android:name=".AssistantRecognitionService"
             android:exported="true"
             android:label="Test Voice Interaction Service">
             <intent-filter>
-                <action android:name="android.speech.RecognitionService" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.speech.RecognitionService"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <meta-data
                 android:name="android.speech"
-                android:resource="@xml/recognition_service" />
+                android:resource="@xml/recognition_service"/>
         </service>
         <service
             android:name=".AssistantInteractionService"
@@ -236,12 +305,12 @@
             android:label="Test Voice Interaction Service"
             android:permission="android.permission.BIND_VOICE_INTERACTION">
             <intent-filter>
-                <action android:name="android.service.voice.VoiceInteractionService" />
+                <action android:name="android.service.voice.VoiceInteractionService"/>
             </intent-filter>
             <meta-data
                 android:name="android.voice_interaction"
-                android:resource="@xml/interaction_service" />
+                android:resource="@xml/interaction_service"/>
         </service>
     </application>
-    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
+    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
 </manifest>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/drawable/bg.png b/tests/FlickerTests/test-apps/flickerapp/res/drawable/bg.png
new file mode 100644
index 0000000..d424a17
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/drawable/bg.png
Binary files differ
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_bubble.xml b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_bubble.xml
new file mode 100644
index 0000000..4ea156d
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_bubble.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7.2,14.4m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M14.8,18m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15.2,8.8m-4.8,0a4.8,4.8 0,1 1,9.6 0a4.8,4.8 0,1 1,-9.6 0"/>
+</vector>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_message.xml b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_message.xml
new file mode 100644
index 0000000..45ed98c
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/drawable/ic_message.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M12,4c-4.97,0 -9,3.58 -9,8c0,1.53 0.49,2.97 1.33,4.18c0.12,0.18 0.2,0.46 0.1,0.66c-0.33,0.68 -0.79,1.52 -1.38,2.39c-0.12,0.17 0.01,0.41 0.21,0.39c0.63,-0.05 1.86,-0.26 3.38,-0.91c0.17,-0.07 0.36,-0.06 0.52,0.03C8.55,19.54 10.21,20 12,20c4.97,0 9,-3.58 9,-8S16.97,4 12,4zM16.94,11.63l-3.29,3.29c-0.13,0.13 -0.34,0.04 -0.34,-0.14v-1.57c0,-0.11 -0.1,-0.21 -0.21,-0.2c-2.19,0.06 -3.65,0.65 -5.14,1.95c-0.15,0.13 -0.38,0 -0.33,-0.19c0.7,-2.57 2.9,-4.57 5.5,-4.75c0.1,-0.01 0.18,-0.09 0.18,-0.19V8.2c0,-0.18 0.22,-0.27 0.34,-0.14l3.29,3.29C17.02,11.43 17.02,11.55 16.94,11.63z"
+      android:fillColor="#000000"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml
new file mode 100644
index 0000000..7c7b2ca
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_bubble.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <Button
+        android:id="@+id/button_finish"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:layout_marginStart="8dp"
+        android:text="Finish" />
+    <Button
+        android:id="@+id/button_new_task"
+        android:layout_width="wrap_content"
+        android:layout_height="46dp"
+        android:layout_marginStart="8dp"
+        android:text="New Task" />
+    <Button
+        android:id="@+id/button_new_bubble"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
+        android:text="New Bubble" />
+
+    <Button
+        android:id="@+id/button_activity_for_result"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dp"
+        android:layout_marginStart="8dp"
+        android:text="Activity For Result" />
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_button.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml
similarity index 100%
rename from tests/FlickerTests/test-apps/flickerapp/res/layout/activity_button.xml
rename to tests/FlickerTests/test-apps/flickerapp/res/layout/activity_launch_new.xml
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_main.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_main.xml
new file mode 100644
index 0000000..553c7fe0
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_main.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/black">
+
+        <Button
+            android:id="@+id/button_create"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:text="Add Bubble" />
+
+        <Button
+            android:id="@+id/button_cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/button_create"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="20dp"
+            android:text="Cancel Bubble" />
+
+        <Button
+            android:id="@+id/button_cancel_all"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/button_cancel"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="20dp"
+            android:text="Cancel All Bubble" />
+</RelativeLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_notification.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_notification.xml
new file mode 100644
index 0000000..7c11984
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_notification.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/black">
+
+        <Button
+            android:id="@+id/button_send_notification"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:text="Send Notification" />
+</RelativeLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
new file mode 100644
index 0000000..f7ba45b
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/holo_blue_bright">
+
+    <!-- All the buttons (and other clickable elements) should be arranged in a way so that it is
+         possible to "cycle" over all them by clicking on the D-Pad DOWN button. The way we do it
+         here is by arranging them this vertical LL and by relying on the nextFocusDown attribute
+         where things are arranged differently and to circle back up to the top once we reach the
+         bottom. -->
+
+    <Button
+        android:id="@+id/enter_pip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Enter PIP"
+        android:onClick="enterPip"/>
+
+    <CheckBox
+        android:id="@+id/with_custom_actions"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="With custom actions"/>
+
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:checkedButton="@id/enter_pip_on_leave_disabled">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Enter PiP on home press"/>
+
+        <RadioButton
+            android:id="@+id/enter_pip_on_leave_disabled"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Disabled"
+            android:onClick="onAutoPipSelected"/>
+
+        <RadioButton
+            android:id="@+id/enter_pip_on_leave_manual"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Via code behind"
+            android:onClick="onAutoPipSelected"/>
+
+        <RadioButton
+            android:id="@+id/enter_pip_on_leave_autoenter"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Auto-enter PiP"
+            android:onClick="onAutoPipSelected"/>
+    </RadioGroup>
+
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:checkedButton="@id/ratio_default">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Ratio"/>
+
+        <RadioButton
+            android:id="@+id/ratio_default"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Default"
+            android:onClick="onRatioSelected"/>
+
+        <RadioButton
+            android:id="@+id/ratio_square"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Square [1:1]"
+            android:onClick="onRatioSelected"/>
+
+        <RadioButton
+            android:id="@+id/ratio_wide"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Wide [2:1]"
+            android:onClick="onRatioSelected"/>
+
+        <RadioButton
+            android:id="@+id/ratio_tall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Tall [1:2]"
+            android:onClick="onRatioSelected"/>
+    </RadioGroup>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Media Session"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button
+            android:id="@+id/media_session_start"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:nextFocusDown="@id/media_session_stop"
+            android:text="Start"/>
+
+        <Button
+            android:id="@+id/media_session_stop"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:nextFocusDown="@id/enter_pip"
+            android:text="Stop"/>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml
new file mode 100644
index 0000000..79e88e4
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/holo_green_light">
+
+    <TextView
+        android:id="@+id/SplitScreenTest"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:gravity="center_vertical|center_horizontal"
+        android:textIsSelectable="true"
+        android:text="PrimaryActivity"
+        android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml
new file mode 100644
index 0000000..ed9feaf
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_splitscreen_secondary.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/holo_blue_light">
+
+    <TextView
+        android:id="@+id/SplitScreenTest"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:gravity="center_vertical|center_horizontal"
+        android:text="SecondaryActivity"
+        android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
index 166e3ca..04a590d 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.server.wm.flicker.testapp;
 
-import static com.android.server.wm.flicker.testapp.ActivityOptions.ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME;
-import static com.android.server.wm.flicker.testapp.ActivityOptions.ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME;
-
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
@@ -39,8 +36,6 @@
     private static final String TAG = "ActivityEmbeddingMainActivity";
     private static final float DEFAULT_SPLIT_RATIO = 0.5f;
 
-    private ActivityEmbeddingComponent mEmbeddingComponent;
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -51,20 +46,24 @@
 
     /** R.id.launch_placeholder_split_button onClick */
     public void launchPlaceholderSplit(View view) {
-        startActivity(new Intent().setComponent(
-                ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME));
+        startActivity(
+                new Intent().setComponent(
+                        ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
+                )
+        );
     }
 
     private void initializeSplitRules() {
-        mEmbeddingComponent = ActivityEmbeddingAppHelper.getActivityEmbeddingComponent();
-        if (mEmbeddingComponent == null) {
+        ActivityEmbeddingComponent embeddingComponent =
+                ActivityEmbeddingAppHelper.getActivityEmbeddingComponent();
+        if (embeddingComponent == null) {
             // Embedding not supported
             Log.d(TAG, "ActivityEmbedding is not supported on this device");
             finish();
             return;
         }
 
-        mEmbeddingComponent.setEmbeddingRules(getSplitRules());
+        embeddingComponent.setEmbeddingRules(getSplitRules());
     }
 
     private Set<EmbeddingRule> getSplitRules() {
@@ -72,10 +71,10 @@
 
         final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule.Builder(
                 new Intent().setComponent(
-                        ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME),
+                        ActivityOptions.ActivityEmbedding.PlaceholderSecondaryActivity.COMPONENT),
                 activity -> activity instanceof ActivityEmbeddingPlaceholderPrimaryActivity,
                 intent -> intent.getComponent().equals(
-                        ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME),
+                        ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT),
                 windowMetrics -> true)
                 .setSplitRatio(DEFAULT_SPLIT_RATIO)
                 .build();
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 cae3df4..5b1ca1f 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
@@ -19,94 +19,181 @@
 import android.content.ComponentName;
 
 public class ActivityOptions {
-    public static final String EXTRA_STARVE_UI_THREAD = "StarveUiThread";
     public static final String FLICKER_APP_PACKAGE = "com.android.server.wm.flicker.testapp";
 
-    public static final String SEAMLESS_ACTIVITY_LAUNCHER_NAME = "SeamlessApp";
-    public static final ComponentName SEAMLESS_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".SeamlessRotationActivity");
+    public static class SimpleActivity {
+        public static final String LABEL = "SimpleActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".SimpleActivity");
+    }
 
-    public static final String IME_ACTIVITY_AUTO_FOCUS_LAUNCHER_NAME = "ImeAppAutoFocus";
-    public static final ComponentName IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".ImeActivityAutoFocus");
+    public static class SeamlessRotation {
+        public static final String LABEL = "SeamlessRotationActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".SeamlessRotationActivity");
 
-    public static final String IME_ACTIVITY_LAUNCHER_NAME = "ImeActivity";
-    public static final ComponentName IME_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
+        public static final String EXTRA_STARVE_UI_THREAD = "StarveUiThread";
+    }
+
+    public static class Ime {
+        public static class Default {
+            public static final String LABEL = "ImeActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
                     FLICKER_APP_PACKAGE + ".ImeActivity");
+        }
 
-    public static final String IME_ACTIVITY_INITIALIZE_LAUNCHER_NAME = "ImeStateInitializeActivity";
-    public static final ComponentName IME_ACTIVITY_INITIALIZE_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
+        public static class AutoFocusActivity {
+            public static final String LABEL = "ImeAppAutoFocus";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".ImeActivityAutoFocus");
+        }
+
+        public static class StateInitializeActivity {
+            public static final String LABEL = "ImeStateInitializeActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
                     FLICKER_APP_PACKAGE + ".ImeStateInitializeActivity");
+        }
 
-    public static final String SIMPLE_ACTIVITY_LAUNCHER_NAME = "SimpleApp";
-    public static final ComponentName SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".SimpleActivity");
-
-    public static final String NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME = "NonResizeableApp";
-    public static final ComponentName NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".NonResizeableActivity");
-
-    public static final String BUTTON_ACTIVITY_LAUNCHER_NAME = "ButtonApp";
-    public static final ComponentName BUTTON_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".ButtonActivity");
-
-    public static final String LAUNCH_NEW_TASK_ACTIVITY_LAUNCHER_NAME = "LaunchNewTaskApp";
-    public static final ComponentName LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".LaunchNewTaskActivity");
-
-    public static final String DIALOG_THEMED_ACTIVITY = "DialogThemedActivity";
-    public static final ComponentName DIALOG_THEMED_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".DialogThemedActivity");
-
-    public static final String PORTRAIT_ONLY_ACTIVITY_LAUNCHER_NAME = "PortraitOnlyActivity";
-    public static final ComponentName PORTRAIT_ONLY_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".PortraitOnlyActivity");
-
-    public static final String EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME =
-            "ImeEditorPopupDialogActivity";
-    public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
+        public static class EditorPopupDialogActivity {
+            public static final String LABEL = "ImeEditorPopupDialogActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
                     FLICKER_APP_PACKAGE + ".ImeEditorPopupDialogActivity");
+        }
+    }
 
-    public static final String SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME = "ShowWhenLockedApp";
-    public static final ComponentName SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".ShowWhenLockedActivity");
+    public static class NonResizeableActivity {
+        public static final String LABEL = "NonResizeableActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".NonResizeableActivity");
+    }
 
-    public static final String NOTIFICATION_ACTIVITY_LAUNCHER_NAME = "NotificationApp";
-    public static final ComponentName NOTIFICATION_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                    FLICKER_APP_PACKAGE + ".NotificationActivity");
+    public static class DialogThemedActivity {
+        public static final String LABEL = "DialogThemedActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".DialogThemedActivity");
+    }
 
-    public static final String ACTIVITY_EMBEDDING_LAUNCHER_NAME = "ActivityEmbeddingMainActivity";
-    public static final ComponentName ACTIVITY_EMBEDDING_MAIN_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
+    public static class PortraitOnlyActivity {
+        public static final String LABEL = "PortraitOnlyActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".PortraitOnlyActivity");
+        public static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
+    }
+
+    public static class ActivityEmbedding {
+        public static class MainActivity {
+            public static final String LABEL = "ActivityEmbeddingMainActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
                     FLICKER_APP_PACKAGE + ".ActivityEmbeddingMainActivity");
-    public static final ComponentName
-            ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME = new ComponentName(
-                    FLICKER_APP_PACKAGE,
-            FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderPrimaryActivity");
-    public static final ComponentName
-            ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME = new ComponentName(
-                    FLICKER_APP_PACKAGE,
-            FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderSecondaryActivity");
+        }
 
-    public static final String MAIL_ACTIVITY_LAUNCHER_NAME = "MailActivity";
-    public static final ComponentName MAIL_ACTIVITY_COMPONENT_NAME = new ComponentName(
-            FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".MailActivity");
+        public static class PlaceholderPrimaryActivity {
+            public static final String LABEL = "ActivityEmbeddingPlaceholderPrimaryActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderPrimaryActivity");
+        }
 
-    public static final String GAME_ACTIVITY_LAUNCHER_NAME = "GameApp";
-    public static final ComponentName GAME_ACTIVITY_COMPONENT_NAME =
-            new ComponentName(FLICKER_APP_PACKAGE,
-                   FLICKER_APP_PACKAGE + ".GameActivity");
+        public static class PlaceholderSecondaryActivity {
+            public static final String LABEL = "ActivityEmbeddingPlaceholderSecondaryActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderSecondaryActivity");
+        }
+    }
+
+    public static class Notification {
+        public static final String LABEL = "NotificationActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".NotificationActivity");
+    }
+
+    public static class Mail {
+        public static final String LABEL = "MailActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".MailActivity");
+    }
+
+    public static class ShowWhenLockedActivity {
+        public static final String LABEL = "ShowWhenLockedActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".ShowWhenLockedActivity");
+    }
+
+    public static class LaunchNewTask {
+        public static final String LABEL = "LaunchNewTaskActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".LaunchNewTaskActivity");
+    }
+
+    public static class Game {
+        public static final String LABEL = "GameActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".GameActivity");
+    }
+
+    public static class LaunchNewActivity {
+        public static final String LABEL = "LaunchNewActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".LaunchNewActivity");
+    }
+
+    public static class PipActivity {
+        // Test App > Pip Activity
+        public static final String LABEL = "PipActivity";
+        public static final String MENU_ACTION_NO_OP = "No-Op";
+        public static final String MENU_ACTION_ON = "On";
+        public static final String MENU_ACTION_OFF = "Off";
+        public static final String MENU_ACTION_CLEAR = "Clear";
+
+        // Intent action that this activity dynamically registers to enter picture-in-picture
+        public static final String ACTION_ENTER_PIP =
+                FLICKER_APP_PACKAGE + ".PipActivity.ENTER_PIP";
+        // Intent action that this activity dynamically registers to set requested orientation.
+        // Will apply the oriention to the value set in the EXTRA_FIXED_ORIENTATION extra.
+        public static final String ACTION_SET_REQUESTED_ORIENTATION =
+                FLICKER_APP_PACKAGE + ".PipActivity.SET_REQUESTED_ORIENTATION";
+
+        // Calls enterPictureInPicture() on creation
+        public static final String EXTRA_ENTER_PIP = "enter_pip";
+        // Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation}
+        public static final String EXTRA_PIP_ORIENTATION = "fixed_orientation";
+        // Adds a click listener to finish this activity when it is clicked
+        public static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
+
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".PipActivity");
+    }
+
+    public static class SplitScreenActivity {
+        public static class Primary {
+            public static final String LABEL = "SplitScreenPrimaryActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".SplitScreenActivity");
+        }
+
+        public static class Secondary {
+            public static final String LABEL = "SplitScreenSecondaryActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".SplitScreenSecondaryActivity");
+        }
+    }
+
+    public static class SendNotificationActivity {
+        public static final String LABEL = "SendNotificationActivity";
+        public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".SendNotificationActivity");
+    }
+
+    public static class Bubbles {
+        public static class LaunchBubble {
+            public static final String LABEL = "LaunchBubbleActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".LaunchBubbleActivity");
+        }
+
+        public static class BubbleActivity {
+            public static final String LABEL = "BubbleActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".BubbleActivity");
+        }
+    }
 }
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleActivity.java
new file mode 100644
index 0000000..58d7e67
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleActivity.java
@@ -0,0 +1,77 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Toast;
+
+public class BubbleActivity extends Activity {
+    private int mNotifId = 0;
+
+    public BubbleActivity() {
+        super();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        if (intent != null) {
+            mNotifId = intent.getIntExtra(BubbleHelper.EXTRA_BUBBLE_NOTIF_ID, -1);
+        } else {
+            mNotifId = -1;
+        }
+
+        setContentView(R.layout.activity_bubble);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        String result = resultCode == Activity.RESULT_OK ? "OK" : "CANCELLED";
+        Toast.makeText(this, "Activity result: " + result, Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java
new file mode 100644
index 0000000..c92b82b
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BubbleHelper.java
@@ -0,0 +1,173 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Person;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
+import android.service.notification.StatusBarNotification;
+import android.view.WindowManager;
+
+import java.util.HashMap;
+
+public class BubbleHelper {
+
+    static final String EXTRA_BUBBLE_NOTIF_ID = "EXTRA_BUBBLE_NOTIF_ID";
+    static final String CHANNEL_ID = "bubbles";
+    static final String CHANNEL_NAME = "Bubbles";
+    static final int DEFAULT_HEIGHT_DP = 300;
+
+    private static BubbleHelper sInstance;
+
+    private final Context mContext;
+    private NotificationManager mNotificationManager;
+    private float mDisplayHeight;
+
+    private HashMap<Integer, BubbleInfo> mBubbleMap = new HashMap<>();
+
+    private int mNextNotifyId = 0;
+    private int mColourIndex = 0;
+
+    public static class BubbleInfo {
+        public int id;
+        public int height;
+        public Icon icon;
+
+        public BubbleInfo(int id, int height, Icon icon) {
+            this.id = id;
+            this.height = height;
+            this.icon = icon;
+        }
+    }
+
+    public static BubbleHelper getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new BubbleHelper(context);
+        }
+        return sInstance;
+    }
+
+    private BubbleHelper(Context context) {
+        mContext = context;
+        mNotificationManager = context.getSystemService(NotificationManager.class);
+
+        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
+                NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setDescription("Channel that posts bubbles");
+        channel.setAllowBubbles(true);
+        mNotificationManager.createNotificationChannel(channel);
+
+        Point p = new Point();
+        WindowManager wm = context.getSystemService(WindowManager.class);
+        wm.getDefaultDisplay().getRealSize(p);
+        mDisplayHeight = p.y;
+
+    }
+
+    private int getNextNotifyId() {
+        int id = mNextNotifyId;
+        mNextNotifyId++;
+        return id;
+    }
+
+    private Icon getIcon() {
+        return Icon.createWithResource(mContext, R.drawable.bg);
+    }
+
+    public int addNewBubble(boolean autoExpand, boolean suppressNotif) {
+        int id = getNextNotifyId();
+        BubbleInfo info = new BubbleInfo(id, DEFAULT_HEIGHT_DP, getIcon());
+        mBubbleMap.put(info.id, info);
+
+        Notification.BubbleMetadata data = getBubbleBuilder(info)
+                .setSuppressNotification(suppressNotif)
+                .setAutoExpandBubble(false)
+                .build();
+        Notification notification = getNotificationBuilder(info.id)
+                .setBubbleMetadata(data).build();
+
+        mNotificationManager.notify(info.id, notification);
+        return info.id;
+    }
+
+    private Notification.Builder getNotificationBuilder(int id) {
+        Person chatBot = new Person.Builder()
+                .setBot(true)
+                .setName("BubbleChat")
+                .setImportant(true)
+                .build();
+        String shortcutId = "BubbleChat";
+        return new Notification.Builder(mContext, CHANNEL_ID)
+                .setChannelId(CHANNEL_ID)
+                .setShortcutId(shortcutId)
+                .setContentTitle("BubbleChat")
+                .setContentIntent(PendingIntent.getActivity(mContext, 0,
+                        new Intent(mContext, LaunchBubbleActivity.class),
+                        PendingIntent.FLAG_UPDATE_CURRENT))
+                .setStyle(new Notification.MessagingStyle(chatBot)
+                        .setConversationTitle("BubbleChat")
+                        .addMessage("BubbleChat",
+                                SystemClock.currentThreadTimeMillis() - 300000, chatBot)
+                        .addMessage("Is it me, " + id + ", you're looking for?",
+                                SystemClock.currentThreadTimeMillis(), chatBot)
+                )
+                .setSmallIcon(R.drawable.ic_bubble);
+    }
+
+    private Notification.BubbleMetadata.Builder getBubbleBuilder(BubbleInfo info) {
+        Intent target = new Intent(mContext, BubbleActivity.class);
+        target.putExtra(EXTRA_BUBBLE_NOTIF_ID, info.id);
+        PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, info.id, target,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        return new Notification.BubbleMetadata.Builder()
+                .setIntent(bubbleIntent)
+                .setIcon(info.icon)
+                .setDesiredHeight(info.height);
+    }
+
+    public void cancel(int id) {
+        mNotificationManager.cancel(id);
+    }
+
+    public void cancelAll() {
+        mNotificationManager.cancelAll();
+    }
+
+    public void cancelLast() {
+        StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications();
+        if (activeNotifications.length > 0) {
+            mNotificationManager.cancel(
+                    activeNotifications[activeNotifications.length - 1].getId());
+        }
+    }
+
+    public void cancelFirst() {
+        StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications();
+        if (activeNotifications.length > 0) {
+            mNotificationManager.cancel(activeNotifications[0].getId());
+        }
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/FixedActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/FixedActivity.java
new file mode 100644
index 0000000..722929f
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/FixedActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+import static com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION;
+
+import android.os.Bundle;
+
+public class FixedActivity extends SimpleActivity {
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Set the fixed orientation if requested
+        if (getIntent().hasExtra(EXTRA_FIXED_ORIENTATION)) {
+            final int ori = Integer.parseInt(getIntent().getStringExtra(EXTRA_FIXED_ORIENTATION));
+            setRequestedOrientation(ori);
+        }
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java
new file mode 100644
index 0000000..dea3444
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchBubbleActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+
+import android.app.Activity;
+import android.app.Person;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.view.View;
+
+import java.util.Arrays;
+
+public class LaunchBubbleActivity extends Activity {
+
+    private BubbleHelper mBubbleHelper;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addInboxShortcut(getApplicationContext());
+        mBubbleHelper = BubbleHelper.getInstance(this);
+        setContentView(R.layout.activity_main);
+        findViewById(R.id.button_create).setOnClickListener(this::add);
+        findViewById(R.id.button_cancel).setOnClickListener(this::cancel);
+        findViewById(R.id.button_cancel_all).setOnClickListener(this::cancelAll);
+    }
+
+    private void add(View v) {
+        mBubbleHelper.addNewBubble(false /* autoExpand */, false /* suppressNotif */);
+    }
+
+    private void cancel(View v) {
+        mBubbleHelper.cancelLast();
+    }
+
+    private void cancelAll(View v) {
+        mBubbleHelper.cancelAll();
+    }
+
+    private void addInboxShortcut(Context context) {
+        Icon icon = Icon.createWithResource(this, R.drawable.bg);
+        Person[] persons = new Person[4];
+        for (int i = 0; i < persons.length; i++) {
+            persons[i] = new Person.Builder()
+                    .setBot(false)
+                    .setIcon(icon)
+                    .setName("google" + i)
+                    .setImportant(true)
+                    .build();
+        }
+
+        ShortcutInfo shortcut = new ShortcutInfo.Builder(context, "BubbleChat")
+                .setShortLabel("BubbleChat")
+                .setLongLived(true)
+                .setIntent(new Intent(Intent.ACTION_VIEW))
+                .setIcon(Icon.createWithResource(context, R.drawable.ic_message))
+                .setPersons(persons)
+                .build();
+        ShortcutManager scmanager = context.getSystemService(ShortcutManager.class);
+        scmanager.addDynamicShortcuts(Arrays.asList(shortcut));
+    }
+
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ButtonActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
similarity index 87%
rename from tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ButtonActivity.java
rename to tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
index b42ac2a..e5710c8 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ButtonActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/LaunchNewActivity.java
@@ -22,7 +22,7 @@
 import android.view.WindowManager;
 import android.widget.Button;
 
-public class ButtonActivity extends Activity {
+public class LaunchNewActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -30,11 +30,11 @@
         p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
                 .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
         getWindow().setAttributes(p);
-        setContentView(R.layout.activity_button);
+        setContentView(R.layout.activity_launch_new);
 
         Button button = findViewById(R.id.launch_second_activity);
         button.setOnClickListener(v -> {
-            Intent intent = new Intent(ButtonActivity.this, SimpleActivity.class);
+            Intent intent = new Intent(LaunchNewActivity.this, SimpleActivity.class);
             startActivity(intent);
         });
     }
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
new file mode 100644
index 0000000..cdb1d42
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
@@ -0,0 +1,307 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+import static android.media.MediaMetadata.METADATA_KEY_TITLE;
+import static android.media.session.PlaybackState.ACTION_PAUSE;
+import static android.media.session.PlaybackState.ACTION_PLAY;
+import static android.media.session.PlaybackState.ACTION_STOP;
+import static android.media.session.PlaybackState.STATE_PAUSED;
+import static android.media.session.PlaybackState.STATE_PLAYING;
+import static android.media.session.PlaybackState.STATE_STOPPED;
+
+import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_SET_REQUESTED_ORIENTATION;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.EXTRA_ENTER_PIP;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.EXTRA_PIP_ORIENTATION;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.PictureInPictureParams;
+import android.app.RemoteAction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
+import android.media.MediaMetadata;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Rational;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.RadioButton;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class PipActivity extends Activity {
+    private static final String TAG = PipActivity.class.getSimpleName();
+    /**
+     * A media session title for when the session is in {@link STATE_PLAYING}.
+     * TvPipNotificationTests check whether the actual notification title matches this string.
+     */
+    private static final String TITLE_STATE_PLAYING = "TestApp media is playing";
+    /**
+     * A media session title for when the session is in {@link STATE_PAUSED}.
+     * TvPipNotificationTests check whether the actual notification title matches this string.
+     */
+    private static final String TITLE_STATE_PAUSED = "TestApp media is paused";
+
+    private static final Rational RATIO_DEFAULT = null;
+    private static final Rational RATIO_SQUARE = new Rational(1, 1);
+    private static final Rational RATIO_WIDE = new Rational(2, 1);
+    private static final Rational RATIO_TALL = new Rational(1, 2);
+
+    private static final String PIP_ACTION_NO_OP = "No-Op";
+    private static final String PIP_ACTION_OFF = "Off";
+    private static final String PIP_ACTION_ON = "On";
+    private static final String PIP_ACTION_CLEAR = "Clear";
+    private static final String ACTION_NO_OP = "com.android.wm.shell.flicker.testapp.NO_OP";
+    private static final String ACTION_SWITCH_OFF =
+            "com.android.wm.shell.flicker.testapp.SWITCH_OFF";
+    private static final String ACTION_SWITCH_ON = "com.android.wm.shell.flicker.testapp.SWITCH_ON";
+    private static final String ACTION_CLEAR = "com.android.wm.shell.flicker.testapp.CLEAR";
+
+    private final PictureInPictureParams.Builder mPipParamsBuilder =
+            new PictureInPictureParams.Builder()
+                    .setAspectRatio(RATIO_DEFAULT);
+    private MediaSession mMediaSession;
+    private final PlaybackState.Builder mPlaybackStateBuilder = new PlaybackState.Builder()
+            .setActions(ACTION_PLAY | ACTION_PAUSE | ACTION_STOP)
+            .setState(STATE_STOPPED, 0, 1f);
+    private PlaybackState mPlaybackState = mPlaybackStateBuilder.build();
+    private final MediaMetadata.Builder mMediaMetadataBuilder = new MediaMetadata.Builder();
+
+    private final List<RemoteAction> mSwitchOffActions = new ArrayList<>();
+    private final List<RemoteAction> mSwitchOnActions = new ArrayList<>();
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (isInPictureInPictureMode()) {
+                switch (intent.getAction()) {
+                    case ACTION_SWITCH_ON:
+                        mPipParamsBuilder.setActions(mSwitchOnActions);
+                        break;
+                    case ACTION_SWITCH_OFF:
+                        mPipParamsBuilder.setActions(mSwitchOffActions);
+                        break;
+                    case ACTION_CLEAR:
+                        mPipParamsBuilder.setActions(Collections.emptyList());
+                        break;
+                    case ACTION_NO_OP:
+                        return;
+                    default:
+                        Log.w(TAG, "Unhandled action=" + intent.getAction());
+                        return;
+                }
+                setPictureInPictureParams(mPipParamsBuilder.build());
+            } else {
+                switch (intent.getAction()) {
+                    case ACTION_ENTER_PIP:
+                        enterPip(null);
+                        break;
+                    case ACTION_SET_REQUESTED_ORIENTATION:
+                        setRequestedOrientation(Integer.parseInt(intent.getStringExtra(
+                                EXTRA_PIP_ORIENTATION)));
+                        break;
+                    default:
+                        Log.w(TAG, "Unhandled action=" + intent.getAction());
+                }
+            }
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Window window = getWindow();
+        final WindowManager.LayoutParams layoutParams = window.getAttributes();
+        layoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        window.setAttributes(layoutParams);
+
+        setContentView(R.layout.activity_pip);
+
+        findViewById(R.id.media_session_start)
+                .setOnClickListener(v -> updateMediaSessionState(STATE_PLAYING));
+        findViewById(R.id.media_session_stop)
+                .setOnClickListener(v -> updateMediaSessionState(STATE_STOPPED));
+
+        mMediaSession = new MediaSession(this, "WMShell_TestApp");
+        mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());
+        mMediaSession.setCallback(new MediaSession.Callback() {
+            @Override
+            public void onPlay() {
+                updateMediaSessionState(STATE_PLAYING);
+            }
+
+            @Override
+            public void onPause() {
+                updateMediaSessionState(STATE_PAUSED);
+            }
+
+            @Override
+            public void onStop() {
+                updateMediaSessionState(STATE_STOPPED);
+            }
+        });
+
+        // Build two sets of the custom actions. We'll replace one with the other when 'On'/'Off'
+        // action is invoked.
+        // The first set consists of 3 actions: 1) Off; 2) No-Op; 3) Clear.
+        // The second set consists of 2 actions: 1) On; 2) Clear.
+        // Upon invocation 'Clear' action clear-off all the custom actions, including itself.
+        final Icon icon = Icon.createWithResource(this, android.R.drawable.ic_menu_help);
+        final RemoteAction noOpAction = buildRemoteAction(icon, PIP_ACTION_NO_OP, ACTION_NO_OP);
+        final RemoteAction switchOnAction =
+                buildRemoteAction(icon, PIP_ACTION_ON, ACTION_SWITCH_ON);
+        final RemoteAction switchOffAction =
+                buildRemoteAction(icon, PIP_ACTION_OFF, ACTION_SWITCH_OFF);
+        final RemoteAction clearAllAction = buildRemoteAction(icon, PIP_ACTION_CLEAR, ACTION_CLEAR);
+        mSwitchOffActions.addAll(Arrays.asList(switchOnAction, clearAllAction));
+        mSwitchOnActions.addAll(Arrays.asList(noOpAction, switchOffAction, clearAllAction));
+
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_NO_OP);
+        filter.addAction(ACTION_SWITCH_ON);
+        filter.addAction(ACTION_SWITCH_OFF);
+        filter.addAction(ACTION_CLEAR);
+        filter.addAction(ACTION_SET_REQUESTED_ORIENTATION);
+        filter.addAction(ACTION_ENTER_PIP);
+        registerReceiver(mBroadcastReceiver, filter);
+
+        handleIntentExtra(getIntent());
+    }
+
+    @Override
+    protected void onDestroy() {
+        unregisterReceiver(mBroadcastReceiver);
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onUserLeaveHint() {
+        // Only used when auto PiP is disabled. This is to simulate the behavior that an app
+        // supports regular PiP but not auto PiP.
+        final boolean manuallyEnterPip =
+                ((RadioButton) findViewById(R.id.enter_pip_on_leave_manual)).isChecked();
+        if (manuallyEnterPip) {
+            enterPictureInPictureMode();
+        }
+    }
+
+    private RemoteAction buildRemoteAction(Icon icon, String label, String action) {
+        final Intent intent = new Intent(action);
+        final PendingIntent pendingIntent =
+                PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+        return new RemoteAction(icon, label, label, pendingIntent);
+    }
+
+    public void enterPip(View v) {
+        final boolean withCustomActions =
+                ((CheckBox) findViewById(R.id.with_custom_actions)).isChecked();
+        mPipParamsBuilder.setActions(
+                withCustomActions ? mSwitchOnActions : Collections.emptyList());
+        enterPictureInPictureMode(mPipParamsBuilder.build());
+    }
+
+    public void onAutoPipSelected(View v) {
+        switch (v.getId()) {
+            case R.id.enter_pip_on_leave_manual:
+                // disable auto enter PiP
+            case R.id.enter_pip_on_leave_disabled:
+                mPipParamsBuilder.setAutoEnterEnabled(false);
+                setPictureInPictureParams(mPipParamsBuilder.build());
+                break;
+            case R.id.enter_pip_on_leave_autoenter:
+                mPipParamsBuilder.setAutoEnterEnabled(true);
+                setPictureInPictureParams(mPipParamsBuilder.build());
+                break;
+        }
+    }
+
+    public void onRatioSelected(View v) {
+        switch (v.getId()) {
+            case R.id.ratio_default:
+                mPipParamsBuilder.setAspectRatio(RATIO_DEFAULT);
+                break;
+
+            case R.id.ratio_square:
+                mPipParamsBuilder.setAspectRatio(RATIO_SQUARE);
+                break;
+
+            case R.id.ratio_wide:
+                mPipParamsBuilder.setAspectRatio(RATIO_WIDE);
+                break;
+
+            case R.id.ratio_tall:
+                mPipParamsBuilder.setAspectRatio(RATIO_TALL);
+                break;
+        }
+    }
+
+    private void updateMediaSessionState(int newState) {
+        if (mPlaybackState.getState() == newState) {
+            return;
+        }
+        final String title;
+        switch (newState) {
+            case STATE_PLAYING:
+                title = TITLE_STATE_PLAYING;
+                break;
+            case STATE_PAUSED:
+                title = TITLE_STATE_PAUSED;
+                break;
+            case STATE_STOPPED:
+                title = "";
+                break;
+
+            default:
+                throw new IllegalArgumentException("Unknown state " + newState);
+        }
+
+        mPlaybackStateBuilder.setState(newState, 0, 1f);
+        mPlaybackState = mPlaybackStateBuilder.build();
+
+        mMediaMetadataBuilder.putText(METADATA_KEY_TITLE, title);
+
+        mMediaSession.setPlaybackState(mPlaybackState);
+        mMediaSession.setMetadata(mMediaMetadataBuilder.build());
+        mMediaSession.setActive(newState != STATE_STOPPED);
+    }
+
+    private void handleIntentExtra(Intent intent) {
+        // Set the fixed orientation if requested
+        if (intent.hasExtra(EXTRA_PIP_ORIENTATION)) {
+            final int ori = Integer.parseInt(getIntent().getStringExtra(EXTRA_PIP_ORIENTATION));
+            setRequestedOrientation(ori);
+        }
+        // Enter picture in picture with the given aspect ratio if provided
+        if (intent.hasExtra(EXTRA_ENTER_PIP)) {
+            mPipParamsBuilder.setActions(mSwitchOnActions);
+            enterPip(null);
+        }
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
index 5cf81cb..ce7a005 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
@@ -18,7 +18,7 @@
 
 import static android.os.SystemClock.sleep;
 
-import static com.android.server.wm.flicker.testapp.ActivityOptions.EXTRA_STARVE_UI_THREAD;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD;
 
 import android.app.Activity;
 import android.os.Bundle;
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SendNotificationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SendNotificationActivity.java
new file mode 100644
index 0000000..8868488
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SendNotificationActivity.java
@@ -0,0 +1,61 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+public class SendNotificationActivity extends Activity {
+    private NotificationManager mNotificationManager;
+    private String mChannelId = "Channel id";
+    private String mChannelName = "Channel name";
+    private NotificationChannel mChannel;
+    private int mNotifyId = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_notification);
+        findViewById(R.id.button_send_notification).setOnClickListener(this::sendNotification);
+
+        mChannel = new NotificationChannel(mChannelId, mChannelName,
+                NotificationManager.IMPORTANCE_DEFAULT);
+        mNotificationManager = getSystemService(NotificationManager.class);
+        mNotificationManager.createNotificationChannel(mChannel);
+    }
+
+    private void sendNotification(View v) {
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                new Intent(this, SendNotificationActivity.class),
+                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+        Notification notification = new Notification.Builder(this, mChannelId)
+                .setContentTitle("Notification App")
+                .setContentText("Notification content")
+                .setWhen(System.currentTimeMillis())
+                .setSmallIcon(R.drawable.ic_message)
+                .setContentIntent(pendingIntent)
+                .build();
+
+        mNotificationManager.notify(mNotifyId, notification);
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenActivity.java
new file mode 100644
index 0000000..70196ae
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenActivity.java
@@ -0,0 +1,29 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SplitScreenActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.activity_splitscreen);
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenSecondaryActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenSecondaryActivity.java
new file mode 100644
index 0000000..a8ce8ff
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SplitScreenSecondaryActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SplitScreenSecondaryActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.activity_splitscreen_secondary);
+    }
+}