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

Commit 27b096e0 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[Screen share] Update strings and icon in app chooser activity.

Bug: 352327853
Flag: NONE string changes
Test: Cast single app -> verify app chooser activity says "Choose app to
cast" and has cast icon
Test: Screen record single app -> verify app chooser activity says
"Choose app to record" and has red screen record icon
Test: Share single app -> verify app chooser activity says "Choose app
to share" and has share icon

Change-Id: I4fa96334ccfe6dda52f4e8ac3ac1fbca479e7f2e
parent 2d0d9366
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
        android:background="@*android:drawable/bottomsheet_background">

        <ImageView
            android:id="@+id/media_projection_app_selector_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"
+8 −2
Original line number Diff line number Diff line
@@ -291,6 +291,8 @@
    <string name="screenrecord_permission_dialog_warning_single_app">When you’re recording an app, anything shown or played in that app is recorded. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
    <!-- Button to start a screen recording of the entire screen in the updated screen record dialog that allows to select an app to record [CHAR LIMIT=50]-->
    <string name="screenrecord_permission_dialog_continue_entire_screen">Record screen</string>
    <!-- Title of the activity that allows to select an app to screen record [CHAR LIMIT=70] -->
    <string name="screenrecord_app_selector_title">Choose app to record</string>

    <!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
    <string name="screenrecord_audio_label">Record audio</string>
@@ -1362,8 +1364,8 @@
    <!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
    <string name="media_projection_sys_service_dialog_warning">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>

    <!-- Title of the dialog that allows to select an app to share or record [CHAR LIMIT=NONE] -->
    <string name="screen_share_permission_app_selector_title">Share or record an app</string>
    <!-- Title of the activity that allows users to select an app to share or record [CHAR LIMIT=NONE] -->
    <string name="screen_share_generic_app_selector_title">Share or record an app</string>

    <!-- Media projection that launched from 1P/3P apps -->
    <!-- 1P/3P app media projection permission dialog title. [CHAR LIMIT=NONE] -->
@@ -1381,6 +1383,8 @@
    <string name="media_projection_entry_app_permission_dialog_continue_entire_screen">Share screen</string>
    <!-- 1P/3P apps disabled the single app projection option. [CHAR LIMIT=NONE] -->
    <string name="media_projection_entry_app_permission_dialog_single_app_disabled"><xliff:g id="app_name" example="Meet">%1$s</xliff:g> has disabled this option</string>
    <!-- Title of the activity that allows users to select an app to share to a 1P/3P app [CHAR LIMIT=70] -->
    <string name="media_projection_entry_share_app_selector_title">Choose app to share</string>

    <!-- Casting that launched by SysUI (i.e. when there is no app name) -->
    <!-- System casting media projection permission dialog title. [CHAR LIMIT=100] -->
@@ -1395,6 +1399,8 @@
    <string name="media_projection_entry_cast_permission_dialog_warning_single_app">When you’re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
    <!-- System casting media projection permission button to continue for SysUI casting. [CHAR LIMIT=60] -->
    <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen">Cast screen</string>
    <!-- Title of the activity that allows users to select an app to cast [CHAR LIMIT=70] -->
    <string name="media_projection_entry_cast_app_selector_title">Choose app to cast</string>

    <!-- Other sharing (not recording nor casting) that launched by SysUI (currently not in use) -->
    <!-- System sharing media projection permission dialog title. [CHAR LIMIT=100] -->
+99 −24
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.accessibility.AccessibilityEvent
import android.widget.ImageView
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
@@ -52,6 +56,7 @@ import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRece
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.AsyncActivityLauncher
import java.lang.IllegalArgumentException
import javax.inject.Inject

class MediaProjectionAppSelectorActivity(
@@ -116,6 +121,7 @@ class MediaProjectionAppSelectorActivity(

        super.onCreate(savedInstanceState)
        controller.init()
        setIcon()
        // we override AppList's AccessibilityDelegate set in ResolverActivity.onCreate because in
        // our case this delegate must extend RecyclerViewAccessibilityDelegate, otherwise
        // RecyclerView scrolling is broken
@@ -298,6 +304,29 @@ class MediaProjectionAppSelectorActivity(
    override fun createContentPreviewView(parent: ViewGroup): ViewGroup =
        recentsViewController.createView(parent)

    /** Set up intent for the [ChooserActivity] */
    private fun Intent.configureChooserIntent(
        resources: Resources,
        hostUserHandle: UserHandle,
        personalProfileUserHandle: UserHandle,
    ) {
        // Specify the query intent to show icons for all apps on the chooser screen
        val queryIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
        putExtra(Intent.EXTRA_INTENT, queryIntent)

        // Update the title of the chooser
        putExtra(Intent.EXTRA_TITLE, resources.getString(titleResId))

        // Select host app's profile tab by default
        val selectedProfile =
            if (hostUserHandle == personalProfileUserHandle) {
                PROFILE_PERSONAL
            } else {
                PROFILE_WORK
            }
        putExtra(EXTRA_SELECTED_PROFILE, selectedProfile)
    }

    private val hostUserHandle: UserHandle
        get() {
            val extras =
@@ -321,6 +350,54 @@ class MediaProjectionAppSelectorActivity(
            return intent.getIntExtra(EXTRA_HOST_APP_UID, /* defaultValue= */ -1)
        }

    /**
     * The type of screen sharing being performed. Used to show the right text and icon in the
     * activity.
     */
    private val screenShareType: ScreenShareType?
        get() {
            if (!intent.hasExtra(EXTRA_SCREEN_SHARE_TYPE)) {
                return null
            } else {
                val type = intent.getStringExtra(EXTRA_SCREEN_SHARE_TYPE) ?: return null
                return try {
                    enumValueOf<ScreenShareType>(type)
                } catch (e: IllegalArgumentException) {
                    null
                }
            }
        }

    @get:StringRes
    private val titleResId: Int
        get() =
            when (screenShareType) {
                ScreenShareType.ShareToApp ->
                    R.string.media_projection_entry_share_app_selector_title
                ScreenShareType.SystemCast ->
                    R.string.media_projection_entry_cast_app_selector_title
                ScreenShareType.ScreenRecord -> R.string.screenrecord_app_selector_title
                null -> R.string.screen_share_generic_app_selector_title
            }

    @get:DrawableRes
    private val iconResId: Int
        get() =
            when (screenShareType) {
                ScreenShareType.ShareToApp -> R.drawable.ic_present_to_all
                ScreenShareType.SystemCast -> R.drawable.ic_cast_connected
                ScreenShareType.ScreenRecord -> R.drawable.ic_screenrecord
                null -> R.drawable.ic_present_to_all
            }

    @get:ColorRes
    private val iconTintResId: Int?
        get() =
            when (screenShareType) {
                ScreenShareType.ScreenRecord -> R.color.screenrecord_icon_color
                else -> null
            }

    companion object {
        const val TAG = "MediaProjectionAppSelectorActivity"

@@ -343,30 +420,18 @@ class MediaProjectionAppSelectorActivity(
        const val EXTRA_HOST_APP_UID = "launched_from_host_uid"
        const val KEY_CAPTURE_TARGET = "capture_region"

        /** Set up intent for the [ChooserActivity] */
        private fun Intent.configureChooserIntent(
            resources: Resources,
            hostUserHandle: UserHandle,
            personalProfileUserHandle: UserHandle
        ) {
            // Specify the query intent to show icons for all apps on the chooser screen
            val queryIntent =
                Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
            putExtra(Intent.EXTRA_INTENT, queryIntent)

            // Update the title of the chooser
            val title = resources.getString(R.string.screen_share_permission_app_selector_title)
            putExtra(Intent.EXTRA_TITLE, title)

            // Select host app's profile tab by default
            val selectedProfile =
                if (hostUserHandle == personalProfileUserHandle) {
                    PROFILE_PERSONAL
                } else {
                    PROFILE_WORK
                }
            putExtra(EXTRA_SELECTED_PROFILE, selectedProfile)
        /**
         * The type of screen sharing being performed.
         *
         * The value set for this extra should match the name of a [ScreenShareType].
         */
        const val EXTRA_SCREEN_SHARE_TYPE = "screen_share_type"
    }

    private fun setIcon() {
        val iconView = findViewById<ImageView>(R.id.media_projection_app_selector_icon) ?: return
        iconView.setImageResource(iconResId)
        iconTintResId?.let { iconView.setColorFilter(this.resources.getColor(it, this.theme)) }
    }

    private fun setAppListAccessibilityDelegate() {
@@ -406,4 +471,14 @@ class MediaProjectionAppSelectorActivity(
            return delegate.onRequestSendAccessibilityEvent(host, child, event)
        }
    }

    /** Enum describing what type of app screen sharing is being performed. */
    enum class ScreenShareType {
        /** The selected app will be cast to another device. */
        SystemCast,
        /** The selected app will be shared to another app on the device. */
        ShareToApp,
        /** The selected app will be recorded. */
        ScreenRecord,
    }
}
+22 −26
Original line number Diff line number Diff line
@@ -73,8 +73,7 @@ import javax.inject.Inject;

import dagger.Lazy;

public class MediaProjectionPermissionActivity extends Activity
        implements DialogInterface.OnClickListener {
public class MediaProjectionPermissionActivity extends Activity {
    private static final String TAG = "MediaProjectionPermissionActivity";
    private static final float MAX_APP_NAME_SIZE_PX = 500f;
    private static final String ELLIPSIS = "\u2026";
@@ -269,7 +268,8 @@ public class MediaProjectionPermissionActivity extends Activity
        Consumer<BaseMediaProjectionPermissionDialogDelegate<AlertDialog>> onStartRecordingClicked =
                dialog -> {
                    ScreenShareOption selectedOption = dialog.getSelectedScreenShareOption();
                    grantMediaProjectionPermission(selectedOption.getMode());
                    grantMediaProjectionPermission(
                            selectedOption.getMode(), hasCastingCapabilities);
                };
        Runnable onCancelClicked = () -> finish(RECORD_CANCEL, /* projection= */ null);
        if (hasCastingCapabilities) {
@@ -305,19 +305,6 @@ public class MediaProjectionPermissionActivity extends Activity
        }
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == AlertDialog.BUTTON_POSITIVE) {
            grantMediaProjectionPermission(ENTIRE_SCREEN);
        } else {
            if (mDialog != null) {
                mDialog.dismiss();
            }
            setResult(RESULT_CANCELED);
            finish(RECORD_CANCEL, /* projection= */ null);
        }
    }

    private void setUpDialog(AlertDialog dialog) {
        SystemUIDialog.registerDismissListener(dialog);
        SystemUIDialog.applyFlags(dialog);
@@ -345,25 +332,21 @@ public class MediaProjectionPermissionActivity extends Activity
        return false;
    }

    private void grantMediaProjectionPermission(int screenShareMode) {
    private void grantMediaProjectionPermission(
            int screenShareMode, boolean hasCastingCapabilities) {
        try {
            IMediaProjection projection = MediaProjectionServiceHelper.createOrReuseProjection(
                    mUid, mPackageName, mReviewGrantedConsentRequired);
            if (screenShareMode == ENTIRE_SCREEN) {
                final IMediaProjection projection =
                        MediaProjectionServiceHelper.createOrReuseProjection(mUid, mPackageName,
                                mReviewGrantedConsentRequired);
                final Intent intent = new Intent();
                intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
                        projection.asBinder());
                setCommonIntentExtras(intent, hasCastingCapabilities, projection);
                setResult(RESULT_OK, intent);
                finish(RECORD_CONTENT_DISPLAY, projection);
            }
            if (screenShareMode == SINGLE_APP) {
                IMediaProjection projection = MediaProjectionServiceHelper.createOrReuseProjection(
                        mUid, mPackageName, mReviewGrantedConsentRequired);
                final Intent intent = new Intent(this,
                        MediaProjectionAppSelectorActivity.class);
                intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
                        projection.asBinder());
                setCommonIntentExtras(intent, hasCastingCapabilities, projection);
                intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
                        getHostUserHandle());
                intent.putExtra(
@@ -391,6 +374,19 @@ public class MediaProjectionPermissionActivity extends Activity
        }
    }

    private void setCommonIntentExtras(
            Intent intent,
            boolean hasCastingCapabilities,
            IMediaProjection projection) throws RemoteException {
        intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
                projection.asBinder());
        intent.putExtra(
                MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE,
                hasCastingCapabilities
                        ? MediaProjectionAppSelectorActivity.ScreenShareType.SystemCast.name()
                        : MediaProjectionAppSelectorActivity.ScreenShareType.ShareToApp.name());
    }

    private UserHandle getHostUserHandle() {
        return UserHandle.getUserHandleForUid(getLaunchedFromUid());
    }
+4 −0
Original line number Diff line number Diff line
@@ -146,6 +146,10 @@ class ScreenRecordPermissionDialogDelegate(
                    hostUserHandle
                )
                intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid)
                intent.putExtra(
                    MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE,
                    MediaProjectionAppSelectorActivity.ScreenShareType.ScreenRecord.name,
                )
                activityStarter.startActivity(intent, /* dismissShade= */ true)
            }
            dialog.dismiss()