Merge changes from topic "pss-app-selector-screenshot" into tm-qpr-dev

* changes:
  [Partial Screensharing] Add app selector activity screenshot test
  [Partial Screensharing] Update app selector (ChooserActivity) header
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index fbabf52..a66b405 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -63,6 +63,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.drawable.AnimatedVectorDrawable;
@@ -146,6 +147,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Supplier;
 
 /**
@@ -281,6 +283,7 @@
     private long mQueriedSharingShortcutsTimeMs;
 
     private int mCurrAvailableWidth = 0;
+    private Insets mLastAppliedInsets = null;
     private int mLastNumberOfChildren = -1;
     private int mMaxTargetsPerRow = 1;
 
@@ -1619,6 +1622,8 @@
         if (mChooserMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
             mChooserMultiProfilePagerAdapter.getInactiveListAdapter().destroyAppPredictor();
         }
+        mPersonalAppPredictor = null;
+        mWorkAppPredictor = null;
     }
 
     @Override // ResolverListCommunicator
@@ -2531,7 +2536,11 @@
                 || gridAdapter.calculateChooserTargetWidth(availableWidth)
                 || recyclerView.getAdapter() == null
                 || availableWidth != mCurrAvailableWidth;
+
+        boolean insetsChanged = !Objects.equals(mLastAppliedInsets, mSystemWindowInsets);
+
         if (isLayoutUpdated
+                || insetsChanged
                 || mLastNumberOfChildren != recyclerView.getChildCount()) {
             mCurrAvailableWidth = availableWidth;
             if (isLayoutUpdated) {
@@ -2552,7 +2561,7 @@
                 return;
             }
 
-            if (mLastNumberOfChildren == recyclerView.getChildCount()) {
+            if (mLastNumberOfChildren == recyclerView.getChildCount() && !insetsChanged) {
                 return;
             }
 
@@ -2563,6 +2572,7 @@
                 int offset = calculateDrawerOffset(top, bottom, recyclerView, gridAdapter);
                 mResolverDrawerLayout.setCollapsibleHeightReserved(offset);
                 mEnterTransitionAnimationDelegate.markOffsetCalculated();
+                mLastAppliedInsets = mSystemWindowInsets;
             });
         }
     }
@@ -3055,7 +3065,12 @@
             mChooserMultiProfilePagerAdapter.setupContainerPadding(
                     getActiveEmptyStateView().findViewById(R.id.resolver_empty_state_container));
         }
-        return super.onApplyWindowInsets(v, insets);
+
+        WindowInsets result = super.onApplyWindowInsets(v, insets);
+        if (mResolverDrawerLayout != null) {
+            mResolverDrawerLayout.requestLayout();
+        }
+        return result;
     }
 
     private void setHorizontalScrollingEnabled(boolean enabled) {
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 71919ff..e773a9c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -79,6 +79,11 @@
   <java-symbol type="id" name="deny_button" />
   <java-symbol type="id" name="description" />
   <java-symbol type="id" name="divider" />
+  <java-symbol type="id" name="drag" />
+  <java-symbol type="id" name="profile_pager" />
+  <java-symbol type="id" name="chooser_header" />
+  <java-symbol type="id" name="content_preview_container" />
+  <java-symbol type="id" name="profile_tabhost" />
   <java-symbol type="id" name="edit_query" />
   <java-symbol type="id" name="edittext_container" />
   <java-symbol type="id" name="expand_activities_button" />
diff --git a/packages/SystemUI/res/drawable/ic_present_to_all.xml b/packages/SystemUI/res/drawable/ic_present_to_all.xml
new file mode 100644
index 0000000..d6c9bbe
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_present_to_all.xml
@@ -0,0 +1,25 @@
+ <!--
+  ~ 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"
+     android:tint="?attr/colorControlNormal">
+     <path
+         android:fillColor="@android:color/white"
+         android:pathData="M21,3L3,3c-1.11,0 -2,0.89 -2,2v14c0,1.11 0.89,2 2,2h18c1.11,0 2,-0.89 2,-2L23,5c0,-1.11 -0.89,-2 -2,-2zM21,19.02L3,19.02L3,4.98h18v14.04zM8,12l4,-4 4,4 -1.41,1.41L13,11.83L13,16h-2v-4.17l-1.59,1.59L8,12z"/>
+ </vector>
diff --git a/packages/SystemUI/res/layout/media_projection_app_selector.xml b/packages/SystemUI/res/layout/media_projection_app_selector.xml
new file mode 100644
index 0000000..4ad6849
--- /dev/null
+++ b/packages/SystemUI/res/layout/media_projection_app_selector.xml
@@ -0,0 +1,92 @@
+<?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.
+  -->
+<com.android.internal.widget.ResolverDrawerLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center"
+    androidprv:maxCollapsedHeight="0dp"
+    androidprv:maxCollapsedHeightSmall="56dp"
+    androidprv:maxWidth="@*android:dimen/chooser_width"
+    android:id="@*android:id/contentPanel">
+
+    <LinearLayout
+        android:id="@*android:id/chooser_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        androidprv:layout_alwaysShow="true"
+        android:gravity="center"
+        android:elevation="0dp"
+        android:background="@*android:drawable/bottomsheet_background">
+
+        <ImageView
+            android:id="@*android:id/icon"
+            android:layout_width="@dimen/media_projection_app_selector_icon_size"
+            android:layout_height="@dimen/media_projection_app_selector_icon_size"
+            android:layout_marginTop="@*android:dimen/chooser_edge_margin_normal"
+            android:layout_marginBottom="@*android:dimen/chooser_edge_margin_normal"
+            android:importantForAccessibility="no"
+            android:tint="?android:attr/textColorPrimary"/>
+
+        <TextView android:id="@*android:id/title"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:gravity="center"
+            android:paddingBottom="@*android:dimen/chooser_view_spacing"
+            android:paddingLeft="24dp"
+            android:paddingRight="24dp"/>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@*android:id/content_preview_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+    <TabHost
+        android:id="@*android:id/profile_tabhost"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="?android:attr/colorBackground">
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TabWidget
+                android:id="@*android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone">
+            </TabWidget>
+            <FrameLayout
+                android:id="@*android:id/tabcontent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <com.android.internal.app.ResolverViewPager
+                    android:id="@*android:id/profile_pager"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"/>
+            </FrameLayout>
+        </LinearLayout>
+    </TabHost>
+
+</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e3be365..e5e369e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1440,6 +1440,8 @@
 
     <dimen name="fgs_manager_list_top_spacing">12dp</dimen>
 
+    <dimen name="media_projection_app_selector_icon_size">32dp</dimen>
+
     <!-- Dream overlay related dimensions -->
     <dimen name="dream_overlay_status_bar_height">60dp</dimen>
     <dimen name="dream_overlay_status_bar_margin">40dp</dimen>
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ExternalViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ExternalViewScreenshotTestRule.kt
new file mode 100644
index 0000000..2e391c7
--- /dev/null
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ExternalViewScreenshotTestRule.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.systemui.testing.screenshot
+
+import android.app.Activity
+import android.graphics.Color
+import android.view.View
+import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
+import androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.rules.RuleChain
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+import platform.test.screenshot.*
+
+/**
+ * A rule that allows to run a screenshot diff test on a view that is hosted in another activity.
+ */
+class ExternalViewScreenshotTestRule(emulationSpec: DeviceEmulationSpec) : TestRule {
+
+    private val colorsRule = MaterialYouColorsRule()
+    private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
+    private val screenshotRule =
+        ScreenshotTestRule(
+            SystemUIGoldenImagePathManager(getEmulatedDevicePathConfig(emulationSpec))
+        )
+    private val delegateRule =
+        RuleChain.outerRule(colorsRule).around(deviceEmulationRule).around(screenshotRule)
+    private val matcher = UnitTestBitmapMatcher
+
+    override fun apply(base: Statement, description: Description): Statement {
+        return delegateRule.apply(base, description)
+    }
+
+    /**
+     * Compare the content of the [view] with the golden image identified by [goldenIdentifier] in
+     * the context of [emulationSpec].
+     */
+    fun screenshotTest(goldenIdentifier: String, view: View) {
+        view.removeElevationRecursively()
+
+        ScreenshotRuleAsserter.Builder(screenshotRule)
+            .setScreenshotProvider { view.toBitmap() }
+            .withMatcher(matcher)
+            .build()
+            .assertGoldenImage(goldenIdentifier)
+    }
+
+    /**
+     * Compare the content of the [activity] with the golden image identified by [goldenIdentifier]
+     * in the context of [emulationSpec].
+     */
+    fun activityScreenshotTest(
+        goldenIdentifier: String,
+        activity: Activity,
+    ) {
+        val rootView = activity.window.decorView
+
+        // Hide system bars, remove insets, focus and make sure device-specific cutouts
+        // don't affect screenshots
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            val window = activity.window
+            window.setDecorFitsSystemWindows(false)
+            WindowInsetsControllerCompat(window, rootView).apply {
+                hide(WindowInsetsCompat.Type.systemBars())
+                systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+            }
+
+            window.statusBarColor = Color.TRANSPARENT
+            window.navigationBarColor = Color.TRANSPARENT
+            window.attributes =
+                window.attributes.apply {
+                    layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
+                }
+
+            rootView.removeInsetsRecursively()
+            activity.currentFocus?.clearFocus()
+        }
+
+        screenshotTest(goldenIdentifier, rootView)
+    }
+}
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/TestAppComponentFactory.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/TestAppComponentFactory.kt
new file mode 100644
index 0000000..98e9aaf
--- /dev/null
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/TestAppComponentFactory.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.systemui.testing.screenshot
+
+import android.app.Activity
+import android.content.Intent
+import androidx.core.app.AppComponentFactory
+
+class TestAppComponentFactory : AppComponentFactory() {
+
+    init {
+        instance = this
+    }
+
+    private val overrides: MutableMap<String, () -> Activity> = hashMapOf()
+
+    fun clearOverrides() {
+        overrides.clear()
+    }
+
+    fun <T : Activity> registerActivityOverride(activity: Class<T>, provider: () -> T) {
+        overrides[activity.name] = provider
+    }
+
+    override fun instantiateActivityCompat(
+        cl: ClassLoader,
+        className: String,
+        intent: Intent?
+    ): Activity {
+        return overrides
+            .getOrDefault(className) { super.instantiateActivityCompat(cl, className, intent) }
+            .invoke()
+    }
+
+    companion object {
+
+        private var instance: TestAppComponentFactory? = null
+
+        fun getInstance(): TestAppComponentFactory =
+            instance
+                ?: error(
+                    "TestAppComponentFactory is not initialized, " +
+                        "did you specify it in the manifest?"
+                )
+    }
+}
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
new file mode 100644
index 0000000..b84d26a
--- /dev/null
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.systemui.testing.screenshot
+
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.util.children
+import android.view.WindowInsets
+
+/**
+ * Elevation/shadows is not deterministic when doing hardware rendering, this exentsion allows to
+ * disable it for any view in the hierarchy.
+ */
+fun View.removeElevationRecursively() {
+    this.elevation = 0f
+    (this as? ViewGroup)?.children?.forEach(View::removeElevationRecursively)
+}
+
+/**
+ * Different devices could have different insets (e.g. different height of the navigation bar or
+ * taskbar). This method dispatches empty insets to the whole view hierarchy and removes
+ * the original listener, so the views won't receive real insets.
+ */
+fun View.removeInsetsRecursively() {
+    this.dispatchApplyWindowInsets(WindowInsets.CONSUMED)
+    this.setOnApplyWindowInsetsListener(null)
+    (this as? ViewGroup)?.children?.forEach(View::removeInsetsRecursively)
+}
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewCapture.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewCapture.kt
index c609e6f..cdedc64 100644
--- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewCapture.kt
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewCapture.kt
@@ -1,10 +1,12 @@
 package com.android.systemui.testing.screenshot
 
+import android.annotation.WorkerThread
 import android.app.Activity
 import android.content.Context
 import android.content.ContextWrapper
 import android.graphics.Bitmap
 import android.graphics.Canvas
+import android.graphics.HardwareRenderer
 import android.graphics.Rect
 import android.os.Build
 import android.os.Handler
@@ -19,8 +21,13 @@
 import androidx.concurrent.futures.ResolvableFuture
 import androidx.test.annotation.ExperimentalTestApi
 import androidx.test.core.internal.os.HandlerExecutor
+import androidx.test.espresso.Espresso
 import androidx.test.platform.graphics.HardwareRendererCompat
+import com.google.common.util.concurrent.FutureCallback
+import com.google.common.util.concurrent.Futures
 import com.google.common.util.concurrent.ListenableFuture
+import kotlin.coroutines.suspendCoroutine
+import kotlinx.coroutines.runBlocking
 
 /*
  * This file was forked from androidx/test/core/view/ViewCapture.kt to add [Window] parameter to
@@ -62,6 +69,47 @@
 }
 
 /**
+ * Synchronously captures an image of the view into a [Bitmap]. Synchronous equivalent of
+ * [captureToBitmap].
+ */
+@WorkerThread
+@ExperimentalTestApi
+@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
+fun View.toBitmap(window: Window? = null): Bitmap {
+    if (Looper.getMainLooper() == Looper.myLooper()) {
+        error("toBitmap() can't be called from the main thread")
+    }
+
+    if (!HardwareRenderer.isDrawingEnabled()) {
+        error("Hardware rendering is not enabled")
+    }
+
+    // Make sure we are idle.
+    Espresso.onIdle()
+
+    val mainExecutor = context.mainExecutor
+    return runBlocking {
+        suspendCoroutine { continuation ->
+            Futures.addCallback(
+                captureToBitmap(window),
+                object : FutureCallback<Bitmap> {
+                    override fun onSuccess(result: Bitmap) {
+                        continuation.resumeWith(Result.success(result))
+                    }
+
+                    override fun onFailure(t: Throwable) {
+                        continuation.resumeWith(Result.failure(t))
+                    }
+                },
+                // We know that we are not on the main thread, so we can block the current
+                // thread and wait for the result in the main thread.
+                mainExecutor,
+            )
+        }
+    }
+}
+
+/**
  * Trigger a redraw of the given view.
  *
  * Should only be called on UI thread.
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
index 47e2d2c..0b0595f 100644
--- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
@@ -19,21 +19,13 @@
 import android.app.Activity
 import android.app.Dialog
 import android.graphics.Bitmap
-import android.graphics.HardwareRenderer
-import android.os.Looper
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewGroup.LayoutParams
 import android.view.ViewGroup.LayoutParams.MATCH_PARENT
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import android.view.Window
 import androidx.activity.ComponentActivity
-import androidx.test.espresso.Espresso
 import androidx.test.ext.junit.rules.ActivityScenarioRule
-import com.google.common.util.concurrent.FutureCallback
-import com.google.common.util.concurrent.Futures
-import kotlin.coroutines.suspendCoroutine
-import kotlinx.coroutines.runBlocking
 import org.junit.Assert.assertEquals
 import org.junit.rules.RuleChain
 import org.junit.rules.TestRule
@@ -89,6 +81,8 @@
             // Elevation/shadows is not deterministic when doing hardware rendering, so we disable
             // it for any view in the hierarchy.
             window.decorView.removeElevationRecursively()
+
+            activity.currentFocus?.clearFocus()
         }
 
         // We call onActivity again because it will make sure that our Activity is done measuring,
@@ -150,53 +144,11 @@
         }
     }
 
-    private fun View.removeElevationRecursively() {
-        this.elevation = 0f
-
-        if (this is ViewGroup) {
-            repeat(childCount) { i -> getChildAt(i).removeElevationRecursively() }
-        }
-    }
-
     private fun Dialog.toBitmap(): Bitmap {
         val window = window
         return window.decorView.toBitmap(window)
     }
 
-    private fun View.toBitmap(window: Window? = null): Bitmap {
-        if (Looper.getMainLooper() == Looper.myLooper()) {
-            error("toBitmap() can't be called from the main thread")
-        }
-
-        if (!HardwareRenderer.isDrawingEnabled()) {
-            error("Hardware rendering is not enabled")
-        }
-
-        // Make sure we are idle.
-        Espresso.onIdle()
-
-        val mainExecutor = context.mainExecutor
-        return runBlocking {
-            suspendCoroutine { continuation ->
-                Futures.addCallback(
-                    captureToBitmap(window),
-                    object : FutureCallback<Bitmap> {
-                        override fun onSuccess(result: Bitmap?) {
-                            continuation.resumeWith(Result.success(result!!))
-                        }
-
-                        override fun onFailure(t: Throwable) {
-                            continuation.resumeWith(Result.failure(t))
-                        }
-                    },
-                    // We know that we are not on the main thread, so we can block the current
-                    // thread and wait for the result in the main thread.
-                    mainExecutor,
-                )
-            }
-        }
-    }
-
     enum class Mode(val layoutParams: LayoutParams) {
         WrapContent(LayoutParams(WRAP_CONTENT, WRAP_CONTENT)),
         MatchSize(LayoutParams(MATCH_PARENT, MATCH_PARENT)),
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 53abd99..0f1ee31 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -23,35 +23,47 @@
 import android.os.Bundle
 import android.os.IBinder
 import android.os.ResultReceiver
-import android.view.View
+import android.os.UserHandle
+import android.widget.ImageView
 import com.android.internal.app.ChooserActivity
+import com.android.internal.app.ResolverListController
 import com.android.internal.app.chooser.NotSelectableTargetInfo
 import com.android.internal.app.chooser.TargetInfo
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.util.AsyncActivityLauncher
-import com.android.systemui.R;
-import javax.inject.Inject
+import com.android.systemui.R
+import com.android.internal.R as AndroidR
 
-class MediaProjectionAppSelectorActivity @Inject constructor(
-    private val activityLauncher: AsyncActivityLauncher
+class MediaProjectionAppSelectorActivity constructor(
+    private val activityLauncher: AsyncActivityLauncher,
+    /** This is used to override the dependency in a screenshot test */
+    @VisibleForTesting
+    private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)? = null
 ) : ChooserActivity() {
 
+    override fun getLayoutResource() =
+        R.layout.media_projection_app_selector
+
     public override fun onCreate(bundle: Bundle?) {
         val queryIntent = Intent(Intent.ACTION_MAIN)
             .addCategory(Intent.CATEGORY_LAUNCHER)
         intent.putExtra(Intent.EXTRA_INTENT, queryIntent)
 
-        // TODO(b/235465652) Use resource lexeme
-        intent.putExtra(Intent.EXTRA_TITLE, "Record or cast an app")
+        // TODO(b/240939253): update copies
+        val title = getString(R.string.media_projection_dialog_service_title)
+        intent.putExtra(Intent.EXTRA_TITLE, title)
 
         super.onCreate(bundle)
 
-        // TODO(b/235465652) we should update VisD of the title and add an icon
-        findViewById<View>(R.id.title)?.visibility = View.VISIBLE
+        requireViewById<ImageView>(AndroidR.id.icon).setImageResource(R.drawable.ic_present_to_all)
     }
 
     override fun appliedThemeResId(): Int =
         R.style.Theme_SystemUI_MediaProjectionAppSelector
 
+    override fun createListController(userHandle: UserHandle): ResolverListController =
+        listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
+
     override fun startSelected(which: Int, always: Boolean, filtered: Boolean) {
         val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter
         val targetInfo = currentListAdapter.targetInfoForPosition(which, filtered) ?: return
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
index e33a1b9..9696998 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
@@ -18,8 +18,10 @@
 
 import android.app.Activity
 import com.android.systemui.media.MediaProjectionAppSelectorActivity
+import com.android.systemui.util.AsyncActivityLauncher
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
 
@@ -29,7 +31,17 @@
     @Binds
     @IntoMap
     @ClassKey(MediaProjectionAppSelectorActivity::class)
-    abstract fun provideMediaProjectionAppSelectorActivity(
+    abstract fun bindMediaProjectionAppSelectorActivity(
         activity: MediaProjectionAppSelectorActivity): Activity
 
+    companion object {
+        @Provides
+        fun provideMediaProjectionAppSelectorActivity(
+            activityLauncher: AsyncActivityLauncher
+        ): MediaProjectionAppSelectorActivity {
+            return MediaProjectionAppSelectorActivity(
+                activityLauncher
+            )
+        }
+    }
 }