summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt83
3 files changed, 126 insertions, 68 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
index f004c3a8916f..6c5337418d02 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
@@ -187,44 +187,17 @@ public class MediaProjectionPermissionActivity extends Activity
}
}
- TextPaint paint = new TextPaint();
- paint.setTextSize(42);
-
CharSequence dialogText = null;
CharSequence dialogTitle = null;
- String appName = null;
- if (Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName)) {
+
+ final String appName = extractAppName(aInfo, packageManager);
+ final boolean hasCastingCapabilities =
+ Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName);
+
+ if (hasCastingCapabilities) {
dialogText = getString(R.string.media_projection_sys_service_dialog_warning);
dialogTitle = getString(R.string.media_projection_sys_service_dialog_title);
} else {
- String label = aInfo.loadLabel(packageManager).toString();
-
- // If the label contains new line characters it may push the security
- // message below the fold of the dialog. Labels shouldn't have new line
- // characters anyways, so just truncate the message the first time one
- // is seen.
- final int labelLength = label.length();
- int offset = 0;
- while (offset < labelLength) {
- final int codePoint = label.codePointAt(offset);
- final int type = Character.getType(codePoint);
- if (type == Character.LINE_SEPARATOR
- || type == Character.CONTROL
- || type == Character.PARAGRAPH_SEPARATOR) {
- label = label.substring(0, offset) + ELLIPSIS;
- break;
- }
- offset += Character.charCount(codePoint);
- }
-
- if (label.isEmpty()) {
- label = mPackageName;
- }
-
- String unsanitizedAppName = TextUtils.ellipsize(label,
- paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
- appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
-
String actionText = getString(R.string.media_projection_dialog_warning, appName);
SpannableString message = new SpannableString(actionText);
@@ -255,6 +228,7 @@ public class MediaProjectionPermissionActivity extends Activity
grantMediaProjectionPermission(selectedOption.getMode());
},
() -> finish(RECORD_CANCEL, /* projection= */ null),
+ hasCastingCapabilities,
appName,
overrideDisableSingleAppOption,
mUid,
@@ -289,6 +263,47 @@ public class MediaProjectionPermissionActivity extends Activity
}
}
+ private String extractAppName(ApplicationInfo applicationInfo, PackageManager packageManager) {
+ String label = applicationInfo.loadLabel(packageManager).toString();
+
+ // If the label contains new line characters it may push the security
+ // message below the fold of the dialog. Labels shouldn't have new line
+ // characters anyways, so just truncate the message the first time one
+ // is seen.
+ final int labelLength = label.length();
+ int offset = 0;
+ while (offset < labelLength) {
+ final int codePoint = label.codePointAt(offset);
+ final int type = Character.getType(codePoint);
+ if (type == Character.LINE_SEPARATOR
+ || type == Character.CONTROL
+ || type == Character.PARAGRAPH_SEPARATOR) {
+ label = label.substring(0, offset) + ELLIPSIS;
+ break;
+ }
+ offset += Character.charCount(codePoint);
+ }
+
+ if (label.isEmpty()) {
+ label = mPackageName;
+ }
+
+ TextPaint paint = new TextPaint();
+ paint.setTextSize(42);
+
+ String unsanitizedAppName = TextUtils.ellipsize(label,
+ paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
+ String appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
+
+ // Have app name be the package name as a default fallback, if specific app name can't be
+ // extracted
+ if (appName == null || appName.isEmpty()) {
+ return mPackageName;
+ }
+
+ return appName;
+ }
+
@Override
protected void onDestroy() {
super.onDestroy();
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
index 9ce8070131fa..6d1a4587d089 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
@@ -29,13 +29,20 @@ class MediaProjectionPermissionDialogDelegate(
mediaProjectionConfig: MediaProjectionConfig?,
private val onStartRecordingClicked: Consumer<MediaProjectionPermissionDialogDelegate>,
private val onCancelClicked: Runnable,
- private val appName: String?,
+ private val hasCastingCapabilities: Boolean,
+ appName: String,
forceShowPartialScreenshare: Boolean,
hostUid: Int,
mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
) :
BaseMediaProjectionPermissionDialogDelegate<AlertDialog>(
- createOptionList(context, appName, mediaProjectionConfig, forceShowPartialScreenshare),
+ createOptionList(
+ context,
+ appName,
+ hasCastingCapabilities,
+ mediaProjectionConfig,
+ forceShowPartialScreenshare
+ ),
appName,
hostUid,
mediaProjectionMetricsLogger
@@ -43,7 +50,7 @@ class MediaProjectionPermissionDialogDelegate(
override fun onCreate(dialog: AlertDialog, savedInstanceState: Bundle?) {
super.onCreate(dialog, savedInstanceState)
// TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
- if (appName == null) {
+ if (hasCastingCapabilities) {
setDialogTitle(R.string.media_projection_entry_cast_permission_dialog_title)
setStartButtonText(R.string.media_projection_entry_cast_permission_dialog_continue)
} else {
@@ -65,30 +72,29 @@ class MediaProjectionPermissionDialogDelegate(
companion object {
private fun createOptionList(
context: Context,
- appName: String?,
+ appName: String,
+ hasCastingCapabilities: Boolean,
mediaProjectionConfig: MediaProjectionConfig?,
overrideDisableSingleAppOption: Boolean = false,
): List<ScreenShareOption> {
val singleAppWarningText =
- if (appName == null) {
+ if (hasCastingCapabilities) {
R.string.media_projection_entry_cast_permission_dialog_warning_single_app
} else {
R.string.media_projection_entry_app_permission_dialog_warning_single_app
}
val entireScreenWarningText =
- if (appName == null) {
+ if (hasCastingCapabilities) {
R.string.media_projection_entry_cast_permission_dialog_warning_entire_screen
} else {
R.string.media_projection_entry_app_permission_dialog_warning_entire_screen
}
- // The single app option should only be disabled if there is an app name provided,
- // the client has setup a MediaProjection with
- // MediaProjectionConfig#createConfigForDefaultDisplay, AND it hasn't been overridden by
- // the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override.
+ // The single app option should only be disabled if the client has setup a
+ // MediaProjection with MediaProjectionConfig#createConfigForDefaultDisplay AND
+ // it hasn't been overridden by the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override.
val singleAppOptionDisabled =
- appName != null &&
- !overrideDisableSingleAppOption &&
+ !overrideDisableSingleAppOption &&
mediaProjectionConfig?.regionToCapture ==
MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
index d183c7370713..7dd802878674 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
@@ -47,13 +47,7 @@ class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
private lateinit var dialog: AlertDialog
private val flags = mock<FeatureFlagsClassic>()
- private val onStartRecordingClicked = mock<Runnable>()
- private val mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>()
-
- private val mediaProjectionConfig: MediaProjectionConfig =
- MediaProjectionConfig.createConfigForDefaultDisplay()
- private val appName: String = "testApp"
- private val hostUid: Int = 12345
+ private val appName = "Test App"
private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app
private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen
@@ -73,16 +67,33 @@ class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
}
@Test
- fun showDialog_forceShowPartialScreenShareFalse() {
- // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
- // overrideDisableSingleAppOption = false
- val overrideDisableSingleAppOption = false
- setUpAndShowDialog(overrideDisableSingleAppOption)
+ fun showDefaultDialog() {
+ setUpAndShowDialog()
val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
val secondOptionText =
spinner.adapter
.getDropDownView(1, null, spinner)
+ .findViewById<TextView>(android.R.id.text1)
+ ?.text
+
+ // check that the first option is single app and enabled
+ assertEquals(context.getString(resIdSingleApp), spinner.selectedItem)
+
+ // check that the second option is full screen and enabled
+ assertEquals(context.getString(resIdFullScreen), secondOptionText)
+ }
+
+ @Test
+ fun showDialog_disableSingleApp() {
+ setUpAndShowDialog(
+ mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay()
+ )
+
+ val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
+ val secondOptionWarningText =
+ spinner.adapter
+ .getDropDownView(1, null, spinner)
.findViewById<TextView>(android.R.id.text2)
?.text
@@ -90,15 +101,15 @@ class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
// check that the second option is single app and disabled
- assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionText)
+ assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionWarningText)
}
@Test
- fun showDialog_forceShowPartialScreenShareTrue() {
- // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
- // overrideDisableSingleAppOption = true
- val overrideDisableSingleAppOption = true
- setUpAndShowDialog(overrideDisableSingleAppOption)
+ fun showDialog_disableSingleApp_forceShowPartialScreenShareTrue() {
+ setUpAndShowDialog(
+ mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay(),
+ overrideDisableSingleAppOption = true
+ )
val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
val secondOptionText =
@@ -114,17 +125,43 @@ class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
assertEquals(context.getString(resIdFullScreen), secondOptionText)
}
- private fun setUpAndShowDialog(overrideDisableSingleAppOption: Boolean) {
+ @Test
+ fun showDialog_disableSingleApp_hasCastingCapabilities() {
+ setUpAndShowDialog(
+ mediaProjectionConfig = MediaProjectionConfig.createConfigForDefaultDisplay(),
+ hasCastingCapabilities = true
+ )
+
+ val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_options)
+ val secondOptionWarningText =
+ spinner.adapter
+ .getDropDownView(1, null, spinner)
+ .findViewById<TextView>(android.R.id.text2)
+ ?.text
+
+ // check that the first option is full screen and enabled
+ assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
+
+ // check that the second option is single app and disabled
+ assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionWarningText)
+ }
+
+ private fun setUpAndShowDialog(
+ mediaProjectionConfig: MediaProjectionConfig? = null,
+ overrideDisableSingleAppOption: Boolean = false,
+ hasCastingCapabilities: Boolean = false,
+ ) {
val delegate =
MediaProjectionPermissionDialogDelegate(
context,
mediaProjectionConfig,
- {},
- onStartRecordingClicked,
+ onStartRecordingClicked = {},
+ onCancelClicked = {},
+ hasCastingCapabilities,
appName,
overrideDisableSingleAppOption,
- hostUid,
- mediaProjectionMetricsLogger
+ hostUid = 12345,
+ mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>()
)
dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate)