Merge "Changes to MediaProjection UX." into qt-dev

This commit is contained in:
Narayan Kamath
2019-05-20 07:41:48 +00:00
committed by Android (Google) Code Review
4 changed files with 74 additions and 36 deletions

View File

@@ -1100,7 +1100,10 @@
<string name="battery_saver_notification_action_text">Turn off Battery Saver</string> <string name="battery_saver_notification_action_text">Turn off Battery Saver</string>
<!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] --> <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_text">While recording or casting, <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> can capture any sensitive information, such as audio that you play and your passwords, payment info, photos, and messages.</string> <string name="media_projection_dialog_text">While recording or casting, <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.</string>
<!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_service_text">While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.</string>
<!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] --> <!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_title">Exposing sensitive info during casting/recording </string> <string name="media_projection_dialog_title">Exposing sensitive info during casting/recording </string>

View File

@@ -44,6 +44,7 @@ import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.util.Utils;
public class MediaProjectionPermissionActivity extends Activity public class MediaProjectionPermissionActivity extends Activity
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener { implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
@@ -96,44 +97,50 @@ public class MediaProjectionPermissionActivity extends Activity
TextPaint paint = new TextPaint(); TextPaint paint = new TextPaint();
paint.setTextSize(42); paint.setTextSize(42);
String label = aInfo.loadLabel(packageManager).toString(); CharSequence dialogText = null;
if (Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName)) {
dialogText = getString(R.string.media_projection_dialog_service_text);
} else {
String label = aInfo.loadLabel(packageManager).toString();
// If the label contains new line characters it may push the security // 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 // message below the fold of the dialog. Labels shouldn't have new line
// characters anyways, so just truncate the message the first time one // characters anyways, so just truncate the message the first time one
// is seen. // is seen.
final int labelLength = label.length(); final int labelLength = label.length();
int offset = 0; int offset = 0;
while (offset < labelLength) { while (offset < labelLength) {
final int codePoint = label.codePointAt(offset); final int codePoint = label.codePointAt(offset);
final int type = Character.getType(codePoint); final int type = Character.getType(codePoint);
if (type == Character.LINE_SEPARATOR if (type == Character.LINE_SEPARATOR
|| type == Character.CONTROL || type == Character.CONTROL
|| type == Character.PARAGRAPH_SEPARATOR) { || type == Character.PARAGRAPH_SEPARATOR) {
label = label.substring(0, offset) + ELLIPSIS; label = label.substring(0, offset) + ELLIPSIS;
break; break;
}
offset += Character.charCount(codePoint);
} }
offset += Character.charCount(codePoint);
if (label.isEmpty()) {
label = mPackageName;
}
String unsanitizedAppName = TextUtils.ellipsize(label,
paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
String appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
String actionText = getString(R.string.media_projection_dialog_text, appName);
SpannableString message = new SpannableString(actionText);
int appNameIndex = actionText.indexOf(appName);
if (appNameIndex >= 0) {
message.setSpan(new StyleSpan(Typeface.BOLD),
appNameIndex, appNameIndex + appName.length(), 0);
}
dialogText = message;
} }
if (label.isEmpty()) { String dialogTitle = getString(R.string.media_projection_dialog_title);
label = mPackageName;
}
String unsanitizedAppName = TextUtils.ellipsize(label,
paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
String appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
String actionText = getString(R.string.media_projection_dialog_text, appName);
SpannableString message = new SpannableString(actionText);
int appNameIndex = actionText.indexOf(appName);
if (appNameIndex >= 0) {
message.setSpan(new StyleSpan(Typeface.BOLD),
appNameIndex, appNameIndex + appName.length(), 0);
}
String dialogTitle = getString(R.string.media_projection_dialog_title, appName);
View dialogTitleView = View.inflate(this, R.layout.media_projection_dialog_title, null); View dialogTitleView = View.inflate(this, R.layout.media_projection_dialog_title, null);
TextView titleText = (TextView) dialogTitleView.findViewById(R.id.dialog_title); TextView titleText = (TextView) dialogTitleView.findViewById(R.id.dialog_title);
@@ -141,7 +148,7 @@ public class MediaProjectionPermissionActivity extends Activity
mDialog = new AlertDialog.Builder(this) mDialog = new AlertDialog.Builder(this)
.setCustomTitle(dialogTitleView) .setCustomTitle(dialogTitleView)
.setMessage(message) .setMessage(dialogText)
.setPositiveButton(R.string.media_projection_action_text, this) .setPositiveButton(R.string.media_projection_action_text, this)
.setNegativeButton(android.R.string.cancel, this) .setNegativeButton(android.R.string.cancel, this)
.setOnCancelListener(this) .setOnCancelListener(this)

View File

@@ -35,6 +35,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.util.Utils;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -234,6 +235,10 @@ public class CastControllerImpl implements CastController {
private String getAppName(String packageName) { private String getAppName(String packageName) {
final PackageManager pm = mContext.getPackageManager(); final PackageManager pm = mContext.getPackageManager();
if (Utils.isHeadlessRemoteDisplayProvider(pm, packageName)) {
return "";
}
try { try {
final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0); final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
if (appInfo != null) { if (appInfo != null) {

View File

@@ -14,6 +14,9 @@
package com.android.systemui.util; package com.android.systemui.util;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.View; import android.view.View;
import com.android.systemui.SysUiServiceProvider; import com.android.systemui.SysUiServiceProvider;
@@ -87,4 +90,24 @@ public class Utils {
return mDisabled; return mDisabled;
} }
} }
/**
* Returns {@code true} iff the package {@code packageName} is a headless remote display
* provider, i.e, that the package holds the privileged {@code REMOTE_DISPLAY_PROVIDER}
* permission and that it doesn't host a launcher icon.
*/
public static boolean isHeadlessRemoteDisplayProvider(PackageManager pm, String packageName) {
if (pm.checkPermission(Manifest.permission.REMOTE_DISPLAY_PROVIDER, packageName)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
homeIntent.setPackage(packageName);
return pm.queryIntentActivities(homeIntent, 0).isEmpty();
}
} }