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

Commit 15b64be1 authored by Tony Mak's avatar Tony Mak
Browse files

Support content description with app name

The logic is like:
1. If content description string with app name placeholder is available,
   and we also have a app name, then we will use this string.
2. Otherwise, fallback to content description string without app
   name placeholder.

Test: atest frameworks/base/core/tests/coretests/src/android/view/textclassifier/
Test: Actually see the content description with app name is formatted
      properly

BUG: 128541828

Change-Id: Iee1dc8d4a429d759d9ab3f4b84dc1ad13b698cdb
parent 3acdae62
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ public interface ClassificationIntentFactory {
                context.getString(com.android.internal.R.string.translate),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.translate_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_TRANSLATE)
                        // TODO: Probably better to introduce a "translate" scheme instead of
                        // using EXTRA_TEXT.
+33 −1
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ public final class LabeledIntent {
    @Nullable
    public final String titleWithEntity;
    public final String description;
    @Nullable
    public final String descriptionWithAppName;
    // Do not update this intent.
    public final Intent intent;
    public final int requestCode;
@@ -75,6 +77,7 @@ public final class LabeledIntent {
            @Nullable String titleWithoutEntity,
            @Nullable String titleWithEntity,
            String description,
            @Nullable String descriptionWithAppName,
            Intent intent,
            int requestCode) {
        if (TextUtils.isEmpty(titleWithEntity) && TextUtils.isEmpty(titleWithoutEntity)) {
@@ -84,6 +87,7 @@ public final class LabeledIntent {
        this.titleWithoutEntity = titleWithoutEntity;
        this.titleWithEntity = titleWithEntity;
        this.description = Preconditions.checkNotNull(description);
        this.descriptionWithAppName = descriptionWithAppName;
        this.intent = Preconditions.checkNotNull(intent);
        this.requestCode = requestCode;
    }
@@ -141,11 +145,39 @@ public final class LabeledIntent {
            Log.w(TAG, "Custom titleChooser return null, fallback to the default titleChooser");
            title = DEFAULT_TITLE_CHOOSER.chooseTitle(this, resolveInfo);
        }
        final RemoteAction action = new RemoteAction(icon, title, description, pendingIntent);
        final RemoteAction action =
                new RemoteAction(icon, title, resolveDescription(resolveInfo, pm), pendingIntent);
        action.setShouldShowIcon(shouldShowIcon);
        return new Result(resolvedIntent, action);
    }

    private String resolveDescription(ResolveInfo resolveInfo, PackageManager packageManager) {
        if (!TextUtils.isEmpty(descriptionWithAppName)) {
            // Example string format of descriptionWithAppName: "Use %1$s to open map".
            String applicationName = getApplicationName(resolveInfo, packageManager);
            if (!TextUtils.isEmpty(applicationName)) {
                return String.format(descriptionWithAppName, applicationName);
            }
        }
        return description;
    }

    @Nullable
    private String getApplicationName(
            ResolveInfo resolveInfo, PackageManager packageManager) {
        if (resolveInfo.activityInfo == null) {
            return null;
        }
        if ("android".equals(resolveInfo.activityInfo.packageName)) {
            return null;
        }
        if (resolveInfo.activityInfo.applicationInfo == null) {
            return null;
        }
        return (String) packageManager.getApplicationLabel(
                resolveInfo.activityInfo.applicationInfo);
    }

    private Bundle getFromTextClassifierExtra(@Nullable Bundle textLanguagesBundle) {
        if (textLanguagesBundle != null) {
            final Bundle bundle = new Bundle();
+12 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import java.util.concurrent.TimeUnit;
 * Creates intents based on the classification type.
 * @hide
 */
// TODO: Consider to support {@code descriptionWithAppName}.
public final class LegacyClassificationIntentFactory implements ClassificationIntentFactory {

    private static final String TAG = "LegacyClassificationIntentFactory";
@@ -108,6 +109,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.email),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.email_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_SENDTO)
                        .setData(Uri.parse(String.format("mailto:%s", text))),
                LabeledIntent.DEFAULT_REQUEST_CODE));
@@ -115,6 +117,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.add_contact),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.add_contact_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_INSERT_OR_EDIT)
                        .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
                        .putExtra(ContactsContract.Intents.Insert.EMAIL, text),
@@ -133,6 +136,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                    context.getString(com.android.internal.R.string.dial),
                    /* titleWithEntity */ null,
                    context.getString(com.android.internal.R.string.dial_desc),
                    /* descriptionWithAppName */ null,
                    new Intent(Intent.ACTION_DIAL).setData(
                            Uri.parse(String.format("tel:%s", text))),
                    LabeledIntent.DEFAULT_REQUEST_CODE));
@@ -141,6 +145,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.add_contact),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.add_contact_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_INSERT_OR_EDIT)
                        .setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
                        .putExtra(ContactsContract.Intents.Insert.PHONE, text),
@@ -150,6 +155,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                    context.getString(com.android.internal.R.string.sms),
                    /* titleWithEntity */ null,
                    context.getString(com.android.internal.R.string.sms_desc),
                    /* descriptionWithAppName */ null,
                    new Intent(Intent.ACTION_SENDTO)
                            .setData(Uri.parse(String.format("smsto:%s", text))),
                    LabeledIntent.DEFAULT_REQUEST_CODE));
@@ -166,6 +172,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                    context.getString(com.android.internal.R.string.map),
                    /* titleWithEntity */ null,
                    context.getString(com.android.internal.R.string.map_desc),
                    /* descriptionWithAppName */ null,
                    new Intent(Intent.ACTION_VIEW)
                            .setData(Uri.parse(String.format("geo:0,0?q=%s", encText))),
                    LabeledIntent.DEFAULT_REQUEST_CODE));
@@ -185,6 +192,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.browse),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.browse_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_VIEW)
                        .setDataAndNormalize(Uri.parse(text))
                        .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
@@ -216,6 +224,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.view_flight),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.view_flight_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_WEB_SEARCH)
                        .putExtra(SearchManager.QUERY, text),
                text.hashCode()));
@@ -231,6 +240,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.view_calendar),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.view_calendar_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_VIEW).setData(builder.build()),
                LabeledIntent.DEFAULT_REQUEST_CODE);
    }
@@ -243,6 +253,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.add_calendar_event),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.add_calendar_event_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_INSERT)
                        .setData(CalendarContract.Events.CONTENT_URI)
                        .putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, isAllDay)
@@ -260,6 +271,7 @@ public final class LegacyClassificationIntentFactory implements ClassificationIn
                context.getString(com.android.internal.R.string.define),
                /* titleWithEntity */ null,
                context.getString(com.android.internal.R.string.define_desc),
                /* descriptionWithAppName */ null,
                new Intent(Intent.ACTION_DEFINE)
                        .putExtra(Intent.EXTRA_TEXT, text),
                text.hashCode()));
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ public final class TemplateIntentFactory {
                            remoteActionTemplate.titleWithoutEntity,
                            remoteActionTemplate.titleWithEntity,
                            remoteActionTemplate.description,
                            remoteActionTemplate.descriptionWithAppName,
                            createIntent(remoteActionTemplate),
                            remoteActionTemplate.requestCode == null
                                    ? LabeledIntent.DEFAULT_REQUEST_CODE
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ public class ActionsSuggestionsHelperTest {
                                        "title",
                                        null,
                                        "description",
                                        null,
                                        Intent.ACTION_VIEW,
                                        Uri.parse("http://www.android.com").toString(),
                                        null,
Loading