Only show physical display as recording targed for screen recording
Filter out virtual display from the list of display to be recorded in
the screen recording dialog.
We keep the overlay display since they are gated by a developer option
already and are useful for development purpose.
Test: com.android.systemui.screenrecord.ScreenRecordPermissionDialogDelegateTest#doNotShowVirtualDisplayInDialog
Bug: 362720120
Flag: com.android.media.projection.flags.media_projection_connected_display_no_virtual_device
Change-Id: Ice0d3d38c32db0577f5c818708560142740e647d
diff --git a/media/java/android/media/flags/projection.aconfig b/media/java/android/media/flags/projection.aconfig
index b4dee0c..fa1349c 100644
--- a/media/java/android/media/flags/projection.aconfig
+++ b/media/java/android/media/flags/projection.aconfig
@@ -16,4 +16,16 @@
name: "stop_media_projection_on_call_end"
description: "Stops MediaProjection sessions when a call ends"
bug: "368336349"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "media_projection_connected_display_no_virtual_device"
+ namespace: "media_projection"
+ description: "Filter out display associated with a virtual device for media projection use case"
+ bug: "362720120"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ is_exported: true
+}
+
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
index 534c12c..3a4c993 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt
@@ -18,7 +18,10 @@
import android.content.Intent
import android.hardware.display.DisplayManager
+import android.hardware.display.VirtualDisplay
+import android.hardware.display.VirtualDisplayConfig
import android.os.UserHandle
+import android.platform.test.annotations.RequiresFlagsEnabled
import android.testing.TestableLooper
import android.view.View
import android.widget.Spinner
@@ -42,6 +45,7 @@
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
import junit.framework.Assert.assertEquals
import org.junit.After
import org.junit.Before
@@ -224,6 +228,34 @@
.notifyProjectionRequestCancelled(TEST_HOST_UID)
}
+ @Test
+ @RequiresFlagsEnabled(
+ com.android.media.projection.flags.Flags
+ .FLAG_MEDIA_PROJECTION_CONNECTED_DISPLAY_NO_VIRTUAL_DEVICE
+ )
+ fun doNotShowVirtualDisplayInDialog() {
+ val displayManager = context.getSystemService(DisplayManager::class.java)!!
+ var virtualDisplay: VirtualDisplay? = null
+ try {
+ virtualDisplay =
+ displayManager.createVirtualDisplay(
+ VirtualDisplayConfig.Builder("virtual display", 1, 1, 160).build()
+ )
+ showDialog()
+ val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
+ val adapter = spinner.adapter
+ val virtualDisplayAvailable =
+ (0 until adapter.count)
+ .mapNotNull { adapter.getItem(it) as? String }
+ .any { it.contains("virtual display", ignoreCase = true) }
+ assertWithMessage("A Virtual Display was shown in the list of display to record")
+ .that(virtualDisplayAvailable)
+ .isFalse()
+ } finally {
+ virtualDisplay?.release()
+ }
+ }
+
private fun showDialog() {
dialog.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
index bdc58c1..eb568f7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
@@ -280,6 +280,18 @@
private const val DELAY_MS: Long = 3000
private const val INTERVAL_MS: Long = 1000
+ private val RECORDABLE_DISPLAY_TYPES =
+ intArrayOf(
+ Display.TYPE_OVERLAY,
+ Display.TYPE_EXTERNAL,
+ Display.TYPE_INTERNAL,
+ Display.TYPE_WIFI,
+ )
+
+ private val filterDeviceTypeFlag: Boolean =
+ com.android.media.projection.flags.Flags
+ .mediaProjectionConnectedDisplayNoVirtualDevice()
+
private fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
return listOf(
@@ -302,6 +314,7 @@
),
)
}
+
return listOf(
ScreenShareOption(
SINGLE_APP,
@@ -322,7 +335,10 @@
),
) +
displayManager.displays
- .filter { it.displayId != Display.DEFAULT_DISPLAY }
+ .filter {
+ it.displayId != Display.DEFAULT_DISPLAY &&
+ (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
+ }
.map {
ScreenShareOption(
ENTIRE_SCREEN,