Merge "Update motion for one-handed bouncer."
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
index e6d32ff..06df9568 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
@@ -42,6 +42,9 @@
     <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
     <!-- ATM.removeRootTasksWithActivityTypes() -->
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
+    <!-- Enable bubble notification-->
+    <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+
     <!-- Allow the test to write directly to /sdcard/ -->
     <application android:requestLegacyExternalStorage="true">
         <uses-library android:name="android.test.runner"/>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
new file mode 100644
index 0000000..d66a6e7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import android.app.INotificationManager
+import android.app.Instrumentation
+import android.app.NotificationManager
+import android.content.Context
+import android.os.ServiceManager
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.repetitions
+import com.android.wm.shell.flicker.helpers.LaunchBubbleHelper
+import org.junit.Test
+import org.junit.runners.Parameterized
+
+/**
+ * Base configurations for Bubble flicker tests
+ */
+abstract class BaseBubbleScreen(protected val testSpec: FlickerTestParameter) {
+
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    protected val context: Context = instrumentation.context
+    protected val testApp = LaunchBubbleHelper(instrumentation)
+
+    protected val notifyManager = INotificationManager.Stub.asInterface(
+            ServiceManager.getService(Context.NOTIFICATION_SERVICE))
+
+    protected val packageManager = context.getPackageManager()
+    protected val uid = packageManager.getApplicationInfo(
+            testApp.component.packageName, 0).uid
+
+    protected lateinit var addBubbleBtn: UiObject2
+
+    protected abstract val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+
+    @JvmOverloads
+    protected open fun buildTransition(
+        extraSpec: FlickerBuilder.(Map<String, Any?>) -> Unit = {}
+    ): FlickerBuilder.(Map<String, Any?>) -> Unit {
+        return { configuration ->
+
+            setup {
+                test {
+                    notifyManager.setBubblesAllowed(testApp.component.packageName,
+                            uid, NotificationManager.BUBBLE_PREFERENCE_ALL)
+                    testApp.launchViaIntent(wmHelper)
+                    addBubbleBtn = device.wait(Until.findObject(
+                            By.text("Add Bubble")), FIND_OBJECT_TIMEOUT)
+                }
+            }
+
+            teardown {
+                notifyManager.setBubblesAllowed(testApp.component.packageName,
+                        uid, NotificationManager.BUBBLE_PREFERENCE_NONE)
+                testApp.exit()
+            }
+
+            extraSpec(this, configuration)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun testAppIsAlwaysVisible() {
+        testSpec.assertLayers {
+            this.isVisible(testApp.component)
+        }
+    }
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            repeat { testSpec.config.repetitions }
+            transition(this, testSpec.config)
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                    .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+                            repetitions = 5)
+        }
+
+        const val FIND_OBJECT_TIMEOUT = 2000L
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
new file mode 100644
index 0000000..42eeadf
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import androidx.test.filters.RequiresDevice
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.annotation.Group4
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test launching a new activity from bubble.
+ *
+ * To run this test: `atest WMShellFlickerTests:ExpandBubbleScreen`
+ *
+ * Actions:
+ *     Launch an app and enable app's bubble notification
+ *     Send a bubble notification
+ *     The activity for the bubble is launched
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@Group4
+class ExpandBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) {
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition() {
+            setup {
+                test {
+                    addBubbleBtn?.run { addBubbleBtn.click() } ?: error("Bubble widget not found")
+                }
+            }
+            transitions {
+                val showBubble = device.wait(Until.findObject(
+                        By.res("com.android.systemui", "bubble_view")), FIND_OBJECT_TIMEOUT)
+                showBubble?.run { showBubble.click() } ?: error("Bubble notify not found")
+                device.pressBack()
+            }
+        }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
new file mode 100644
index 0000000..47e8c0c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.annotation.Group4
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test creating a bubble notification
+ *
+ * To run this test: `atest WMShellFlickerTests:LaunchBubbleScreen`
+ *
+ * Actions:
+ *     Launch an app and enable app's bubble notification
+ *     Send a bubble notification
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@Group4
+class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) {
+
+    override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+        get() = buildTransition() {
+            transitions {
+                addBubbleBtn?.run { addBubbleBtn.click() } ?: error("Bubble widget not found")
+            }
+        }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt
new file mode 100644
index 0000000..6695c17
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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 com.android.server.wm.traces.parser.toFlickerComponent
+import com.android.wm.shell.flicker.testapp.Components
+
+class LaunchBubbleHelper(instrumentation: Instrumentation) : BaseAppHelper(
+    instrumentation,
+    Components.LaunchBubbleActivity.LABEL,
+    Components.LaunchBubbleActivity.COMPONENT.toFlickerComponent()
+) {
+
+    companion object {
+        const val TEST_REPETITIONS = 1
+        const val TIMEOUT_MS = 3_000L
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
index 5549330..2cdbffa 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -107,5 +107,20 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <activity
+            android:name=".LaunchBubbleActivity"
+            android:label="LaunchBubbleApp"
+            android:exported="true"
+            android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.intent.action.VIEW" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".BubbleActivity"
+            android:label="BubbleApp"
+            android:exported="false"
+            android:resizeableActivity="true" />
     </application>
 </manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/bg.png b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/bg.png
new file mode 100644
index 0000000..d424a17
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/bg.png
Binary files differ
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_bubble.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_bubble.xml
new file mode 100644
index 0000000..b43f31d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_bubble.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 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/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_message.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_message.xml
new file mode 100644
index 0000000..0e8c7a0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/drawable/ic_message.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 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/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_bubble.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_bubble.xml
new file mode 100644
index 0000000..f8b0ca3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_bubble.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 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/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_main.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_main.xml
new file mode 100644
index 0000000..5c7b18e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_main.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/black">
+
+        <Button
+            android:id="@+id/button_create"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:text="Add Bubble" />
+</FrameLayout>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleActivity.java
new file mode 100644
index 0000000..bc3bc75
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleActivity.java
@@ -0,0 +1,77 @@
+/*
+ * 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.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/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleHelper.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleHelper.java
new file mode 100644
index 0000000..d72c8d5
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/BubbleHelper.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2021 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.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Person;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
+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("BubbleBot")
+                .setImportant(true)
+                .build();
+
+        RemoteInput remoteInput = new RemoteInput.Builder("key")
+                .setLabel("Reply")
+                .build();
+
+        String shortcutId = "BubbleChat";
+        return new Notification.Builder(mContext, CHANNEL_ID)
+                .setChannelId(CHANNEL_ID)
+                .setShortcutId(shortcutId)
+                .setContentIntent(PendingIntent.getActivity(mContext, 0,
+                        new Intent(mContext, LaunchBubbleActivity.class),
+                        PendingIntent.FLAG_UPDATE_CURRENT))
+                .setStyle(new Notification.MessagingStyle(chatBot)
+                        .setConversationTitle("Bubble Chat")
+                        .addMessage("Hello? This is bubble: " + id,
+                                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);
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
index 0ead91b..0ed59bd 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
@@ -87,4 +87,16 @@
         public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
                 PACKAGE_NAME + ".SplitScreenSecondaryActivity");
     }
+
+    public static class LaunchBubbleActivity {
+        public static final String LABEL = "LaunchBubbleApp";
+        public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
+                PACKAGE_NAME + ".LaunchBubbleActivity");
+    }
+
+    public static class BubbleActivity {
+        public static final String LABEL = "BubbleApp";
+        public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
+                PACKAGE_NAME + ".BubbleActivity");
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/LaunchBubbleActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/LaunchBubbleActivity.java
new file mode 100644
index 0000000..c55f9d7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/LaunchBubbleActivity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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.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.os.Handler;
+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);
+    }
+
+    private void add(View v) {
+        mBubbleHelper.addNewBubble(false /* autoExpand */, false /* suppressNotif */);
+    }
+
+    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/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f116641..983c776 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -269,7 +269,7 @@
 
 void ClipPath::draw(SkCanvas* outCanvas, bool useStagingData) {
     SkPath tempStagingPath;
-    outCanvas->clipPath(getUpdatedPath(useStagingData, &tempStagingPath));
+    outCanvas->clipPath(getUpdatedPath(useStagingData, &tempStagingPath), true);
 }
 
 Group::Group(const Group& group) : Node(group) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 23c9408f..bfb63ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -409,21 +409,8 @@
         }
 
         if (mAllowFancy) {
-            // Make brightness appear static position and alpha in through second half.
-            View brightness = mQsPanelController.getBrightnessView();
-            if (brightness != null) {
-                firstPageBuilder.addFloat(brightness, "translationY",
-                        brightness.getMeasuredHeight() * 0.5f, 0);
-                mBrightnessAnimator = new TouchAnimator.Builder()
-                        .addFloat(brightness, "alpha", 0, 1)
-                        .addFloat(brightness, "sliderScaleY", 0.3f, 1)
-                        .setInterpolator(Interpolators.ALPHA_IN)
-                        .setStartDelay(0.3f)
-                        .build();
-                mAllViews.add(brightness);
-            } else {
-                mBrightnessAnimator = null;
-            }
+            animateBrightnessSlider(firstPageBuilder);
+
             mFirstPageAnimator = firstPageBuilder
                     .setListener(this)
                     .build();
@@ -474,20 +461,53 @@
                 .addFloat(tileLayout, "alpha", 0, 1).build();
     }
 
+    private void animateBrightnessSlider(Builder firstPageBuilder) {
+        View qsBrightness = mQsPanelController.getBrightnessView();
+        View qqsBrightness = mQuickQSPanelController.getBrightnessView();
+        if (qqsBrightness != null && qqsBrightness.getVisibility() == View.VISIBLE) {
+            // animating in split shade mode
+            mAnimatedQsViews.add(qsBrightness);
+            mAllViews.add(qqsBrightness);
+            int translationY = getRelativeTranslationY(qsBrightness, qqsBrightness);
+            mBrightnessAnimator = new Builder()
+                    // we need to animate qs brightness even if animation will not be visible,
+                    // as we might start from sliderScaleY set to 0.3 if device was in collapsed QS
+                    // portrait orientation before
+                    .addFloat(qsBrightness, "sliderScaleY", 0.3f, 1)
+                    .addFloat(qqsBrightness, "translationY", 0, translationY)
+                    .build();
+        } else if (qsBrightness != null) {
+            firstPageBuilder.addFloat(qsBrightness, "translationY",
+                    qsBrightness.getMeasuredHeight() * 0.5f, 0);
+            mBrightnessAnimator = new Builder()
+                    .addFloat(qsBrightness, "alpha", 0, 1)
+                    .addFloat(qsBrightness, "sliderScaleY", 0.3f, 1)
+                    .setInterpolator(Interpolators.ALPHA_IN)
+                    .setStartDelay(0.3f)
+                    .build();
+            mAllViews.add(qsBrightness);
+        } else {
+            mBrightnessAnimator = null;
+        }
+    }
+
     private void updateQQSFooterAnimation() {
-        int[] qsPosition = new int[2];
-        int[] qqsPosition = new int[2];
-        View commonView = mQs.getView();
-        getRelativePositionInt(qsPosition, mQSFooterActions, commonView);
-        getRelativePositionInt(qqsPosition, mQQSFooterActions, commonView);
-        int translationY = (qsPosition[1] - qqsPosition[1])
-                - mQuickStatusBarHeader.getOffsetTranslation();
+        int translationY = getRelativeTranslationY(mQSFooterActions, mQQSFooterActions);
         mQQSFooterActionsAnimator = new TouchAnimator.Builder()
                 .addFloat(mQQSFooterActions, "translationY", 0, translationY)
                 .build();
         mAnimatedQsViews.add(mQSFooterActions);
     }
 
+    private int getRelativeTranslationY(View view1, View view2) {
+        int[] qsPosition = new int[2];
+        int[] qqsPosition = new int[2];
+        View commonView = mQs.getView();
+        getRelativePositionInt(qsPosition, view1, commonView);
+        getRelativePositionInt(qqsPosition, view2, commonView);
+        return (qsPosition[1] - qqsPosition[1]) - mQuickStatusBarHeader.getOffsetTranslation();
+    }
+
     private boolean isIconInAnimatedRow(int count) {
         if (mPagedLayout == null) {
             return false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 9025427..70892a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -258,10 +258,6 @@
         return mView.isLayoutRtl();
     }
 
-    public View getBrightnessView() {
-        return mView.getBrightnessView();
-    }
-
     /** */
     public void setPageListener(PagedTileLayout.PageListener listener) {
         mView.setPageListener(listener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 42323e3..97568f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -24,6 +24,7 @@
 import android.content.ComponentName;
 import android.content.res.Configuration;
 import android.metrics.LogMaker;
+import android.view.View;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
@@ -405,6 +406,10 @@
         mUsingHorizontalLayoutChangedListener = listener;
     }
 
+    public View getBrightnessView() {
+        return mView.getBrightnessView();
+    }
+
     /** */
     public static final class TileRecord extends QSPanel.Record {
         public QSTile tile;
diff --git a/services/core/java/com/android/server/am/CacheOomRanker.java b/services/core/java/com/android/server/am/CacheOomRanker.java
index 7413808..e6ffcfc 100644
--- a/services/core/java/com/android/server/am/CacheOomRanker.java
+++ b/services/core/java/com/android/server/am/CacheOomRanker.java
@@ -364,6 +364,7 @@
                 // First element is total RSS:
                 // frameworks/base/core/jni/android_util_Process.cpp:1192
                 scoredProcessRecord.proc.mState.setCacheOomRankerRss(rss[0], nowMs);
+                scoredProcessRecord.proc.mProfile.setLastRss(rss[0]);
             }
         }
 
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 86d7dcd..9be9505 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,8 +16,6 @@
 
 package com.android.server.input;
 
-import static android.view.Surface.ROTATION_0;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
@@ -40,7 +38,6 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayViewport;
@@ -100,7 +97,6 @@
 import android.view.InputEvent;
 import android.view.InputMonitor;
 import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.Surface;
 import android.view.VerifiedInputEvent;
@@ -595,20 +591,9 @@
 
     private void setDisplayViewportsInternal(List<DisplayViewport> viewports) {
         final DisplayViewport[] vArray = new DisplayViewport[viewports.size()];
-        if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
-            // Remove display projection information from DisplayViewport, leaving only the
-            // orientation. The display projection will be built-into the window transforms.
-            for (int i = viewports.size() - 1; i >= 0; --i) {
-                final DisplayViewport v = vArray[i] = viewports.get(i).makeCopy();
-                // Note: the deviceWidth/Height are in rotated with the orientation.
-                v.logicalFrame.set(0, 0, v.deviceWidth, v.deviceHeight);
-                v.physicalFrame.set(0, 0, v.deviceWidth, v.deviceHeight);
-            }
-        } else {
             for (int i = viewports.size() - 1; i >= 0; --i) {
                 vArray[i] = viewports.get(i);
             }
-        }
         nativeSetDisplayViewports(mPtr, vArray);
     }
 
@@ -828,38 +813,6 @@
                 && mode != InputEventInjectionSync.WAIT_FOR_RESULT) {
             throw new IllegalArgumentException("mode is invalid");
         }
-        if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
-            // Motion events that are pointer events or relative mouse events will need to have the
-            // inverse display rotation applied to them.
-            if (event instanceof MotionEvent
-                    && (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
-                    || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE))) {
-                Context displayContext = getContextForDisplay(event.getDisplayId());
-                if (displayContext == null) {
-                    displayContext = Objects.requireNonNull(
-                            getContextForDisplay(Display.DEFAULT_DISPLAY));
-                }
-                final Display display = displayContext.getDisplay();
-                final int rotation = display.getRotation();
-                if (rotation != ROTATION_0) {
-                    final MotionEvent motion = (MotionEvent) event;
-                    // Injections are currently expected to be in the space of the injector (ie.
-                    // usually assumed to be post-rotated). Thus we need to un-rotate into raw
-                    // input coordinates for dispatch.
-                    final Point sz = new Point();
-                    if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
-                        display.getRealSize(sz);
-                        if ((rotation % 2) != 0) {
-                            final int tmpX = sz.x;
-                            sz.x = sz.y;
-                            sz.y = tmpX;
-                        }
-                    }
-                    motion.applyTransform(MotionEvent.createRotateMatrix(
-                            (4 - rotation), sz.x, sz.y));
-                }
-            }
-        }
 
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();