Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5df43f2f authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB][Screen Chips] Show device name in stop dialog when screen casting.

Casting to another device can either trigger MediaRouter APIs (if only
audio is being cast) or MediaProjection APIs (if the screen is being
cast). Change Id9710270bafef03d5f0c4e1cece124df8fd59755 showed the device
name in the stop dialog if MediaRouter APIs were used. This change now
also shows the device name in the stop dialog if MediaProjection APIs
are used.

Fixes: 351851835
Bug: 332662551
Flag: com.android.systemui.status_bar_screen_sharing_chips

Test: Cast screen to another device, then tap chip -> verify stop dialog
includes device name
Test: Cast audio to another device, then tap chip -> verify stop dialog
includes device name
Test: Share your screen with another app, then tap chip -> verify stop
dialog includes name of app receiving the share (this verifies that
nothing goes wrong if we couldn't get the device name)
Test: atest MediaProjectionManagerRepositoryTest

Change-Id: I927471aae423d68357baaa3c7691334b58d09585
parent f9e13dbf
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -28,13 +28,25 @@ sealed interface MediaProjectionState {
     *
     * @property hostPackage the package name of the app that is receiving the content of the media
     *   projection (aka which app the phone screen contents are being sent to).
     * @property hostDeviceName the name of the other device that's receiving the content of the
     *   media projection. Null if the media projection is going to this same device (e.g. another
     *   app is recording the screen).
     */
    sealed class Projecting(open val hostPackage: String) : MediaProjectionState {
    sealed class Projecting(
        open val hostPackage: String,
        open val hostDeviceName: String?,
    ) : MediaProjectionState {
        /** The entire screen is being projected. */
        data class EntireScreen(override val hostPackage: String) : Projecting(hostPackage)
        data class EntireScreen(
            override val hostPackage: String,
            override val hostDeviceName: String? = null,
        ) : Projecting(hostPackage, hostDeviceName)

        /** Only a single task is being projected. */
        data class SingleTask(override val hostPackage: String, val task: RunningTaskInfo) :
            Projecting(hostPackage)
        data class SingleTask(
            override val hostPackage: String,
            override val hostDeviceName: String?,
            val task: RunningTaskInfo,
        ) : Projecting(hostPackage, hostDeviceName)
    }
}
+12 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.mediaprojection.data.repository

import android.app.ActivityManager.RunningTaskInfo
import android.hardware.display.DisplayManager
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
import android.os.Handler
@@ -47,6 +48,7 @@ class MediaProjectionManagerRepository
@Inject
constructor(
    private val mediaProjectionManager: MediaProjectionManager,
    private val displayManager: DisplayManager,
    @Main private val handler: Handler,
    @Application private val applicationScope: CoroutineScope,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
@@ -110,14 +112,21 @@ constructor(
        }

        val hostPackage = info.packageName
        val hostDeviceName =
            withContext(backgroundDispatcher) {
                // If the projection is to a different device, then the session's display ID should
                // identify the display associated with that different device.
                displayManager.getDisplay(session.virtualDisplayId)?.name
            }

        if (session.contentToRecord == RECORD_CONTENT_DISPLAY || session.tokenToRecord == null) {
            return MediaProjectionState.Projecting.EntireScreen(hostPackage)
            return MediaProjectionState.Projecting.EntireScreen(hostPackage, hostDeviceName)
        }
        val matchingTask =
            tasksRepository.findRunningTaskFromWindowContainerToken(
                checkNotNull(session.tokenToRecord)
            ) ?: return MediaProjectionState.Projecting.EntireScreen(hostPackage)
        return MediaProjectionState.Projecting.SingleTask(hostPackage, matchingTask)
            ) ?: return MediaProjectionState.Projecting.EntireScreen(hostPackage, hostDeviceName)
        return MediaProjectionState.Projecting.SingleTask(hostPackage, hostDeviceName, matchingTask)
    }

    companion object {
+7 −6
Original line number Diff line number Diff line
@@ -51,33 +51,34 @@ class EndCastScreenToOtherDeviceDialogDelegate(
    }

    private fun getMessage(): String {
        val hostDeviceName = state.projectionState.hostDeviceName
        return if (state.projectionState is MediaProjectionState.Projecting.SingleTask) {
            val appBeingSharedName =
                endMediaProjectionDialogHelper.getAppName(state.projectionState)
            if (appBeingSharedName != null && state.deviceName != null) {
            if (appBeingSharedName != null && hostDeviceName != null) {
                context.getString(
                    R.string.cast_to_other_device_stop_dialog_message_specific_app_with_device,
                    appBeingSharedName,
                    state.deviceName,
                    hostDeviceName,
                )
            } else if (appBeingSharedName != null) {
                context.getString(
                    R.string.cast_to_other_device_stop_dialog_message_specific_app,
                    appBeingSharedName,
                )
            } else if (state.deviceName != null) {
            } else if (hostDeviceName != null) {
                context.getString(
                    R.string.cast_to_other_device_stop_dialog_message_generic_with_device,
                    state.deviceName
                    hostDeviceName,
                )
            } else {
                context.getString(R.string.cast_to_other_device_stop_dialog_message_generic)
            }
        } else {
            if (state.deviceName != null) {
            if (hostDeviceName != null) {
                context.getString(
                    R.string.cast_to_other_device_stop_dialog_message_entire_screen_with_device,
                    state.deviceName
                    hostDeviceName,
                )
            } else {
                context.getString(
+3 −3
Original line number Diff line number Diff line
@@ -71,11 +71,11 @@ constructor(
                            {
                                str1 = type.name
                                str2 = state.hostPackage
                                str3 = state.hostDeviceName
                            },
                            { "State: Projecting(type=$str1 hostPackage=$str2)" }
                            { "State: Projecting(type=$str1 hostPackage=$str2 hostDevice=$str3)" }
                        )
                        // TODO(b/351851835): Get the device name.
                        ProjectionChipModel.Projecting(type, state, deviceName = null)
                        ProjectionChipModel.Projecting(type, state)
                    }
                }
            }
+1 −7
Original line number Diff line number Diff line
@@ -26,16 +26,10 @@ sealed class ProjectionChipModel {
    /** There is no media being projected. */
    data object NotProjecting : ProjectionChipModel()

    /**
     * Media is currently being projected.
     *
     * @property deviceName the name of the device receiving the projection, or null if the
     *   projection is to this device (as opposed to a different device).
     */
    /** Media is currently being projected. */
    data class Projecting(
        val type: Type,
        val projectionState: MediaProjectionState.Projecting,
        val deviceName: String?,
    ) : ProjectionChipModel()

    enum class Type {
Loading