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

Commit 944836c6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "TextClassifier: Support service intents."

parents 3ac786d2 2f19b92c
Loading
Loading
Loading
Loading
+59 −5
Original line number Diff line number Diff line
@@ -17,11 +17,14 @@
package android.view.textclassifier;

import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -36,6 +39,8 @@ import android.view.textclassifier.TextClassifier.EntityType;

import com.android.internal.util.Preconditions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@@ -109,6 +114,14 @@ public final class TextClassification implements Parcelable {
    private static final int MAX_PRIMARY_ICON_SIZE = 192;
    private static final int MAX_SECONDARY_ICON_SIZE = 144;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {IntentType.UNSUPPORTED, IntentType.ACTIVITY, IntentType.SERVICE})
    private @interface IntentType {
        int UNSUPPORTED = -1;
        int ACTIVITY = 0;
        int SERVICE = 1;
    }

    @NonNull private final String mText;
    @Nullable private final Drawable mPrimaryIcon;
    @Nullable private final String mPrimaryLabel;
@@ -312,17 +325,58 @@ public final class TextClassification implements Parcelable {
    }

    /**
     * Creates an OnClickListener that starts an activity with the specified intent.
     * Creates an OnClickListener that triggers the specified intent.
     * Returns null if the intent is not supported for the specified context.
     *
     * @throws IllegalArgumentException if context or intent is null
     * @hide
     */
    @NonNull
    public static OnClickListener createStartActivityOnClickListener(
    @Nullable
    public static OnClickListener createIntentOnClickListener(
            @NonNull final Context context, @NonNull final Intent intent) {
        switch (getIntentType(intent, context)) {
            case IntentType.ACTIVITY:
                return v -> context.startActivity(intent);
            case IntentType.SERVICE:
                return v -> context.startService(intent);
            default:
                return null;
        }
    }

    @IntentType
    private static int getIntentType(@NonNull Intent intent, @NonNull Context context) {
        Preconditions.checkArgument(context != null);
        Preconditions.checkArgument(intent != null);
        return v -> context.startActivity(intent);

        final ResolveInfo activityRI = context.getPackageManager().resolveActivity(intent, 0);
        if (activityRI != null) {
            if (context.getPackageName().equals(activityRI.activityInfo.packageName)) {
                return IntentType.ACTIVITY;
            }
            final boolean exported = activityRI.activityInfo.exported;
            if (exported && hasPermission(context, activityRI.activityInfo.permission)) {
                return IntentType.ACTIVITY;
            }
        }

        final ResolveInfo serviceRI = context.getPackageManager().resolveService(intent, 0);
        if (serviceRI != null) {
            if (context.getPackageName().equals(serviceRI.serviceInfo.packageName)) {
                return IntentType.SERVICE;
            }
            final boolean exported = serviceRI.serviceInfo.exported;
            if (exported && hasPermission(context, serviceRI.serviceInfo.permission)) {
                return IntentType.SERVICE;
            }
        }

        return IntentType.UNSUPPORTED;
    }

    private static boolean hasPermission(@NonNull Context context, @NonNull String permission) {
        return permission == null
                || context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
+16 −29
Original line number Diff line number Diff line
@@ -4020,10 +4020,11 @@ public class Editor {
            if (textClassification == null) {
                return;
            }
            if (isValidAssistMenuItem(
            final OnClickListener onClick = getSupportedOnClickListener(
                    textClassification.getIcon(),
                    textClassification.getLabel(),
                    textClassification.getIntent())) {
                    textClassification.getIntent());
            if (onClick != null) {
                final MenuItem item = menu.add(
                        TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST,
                        textClassification.getLabel())
@@ -4031,15 +4032,16 @@ public class Editor {
                        .setIntent(textClassification.getIntent());
                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                mAssistClickHandlers.put(
                        item, TextClassification.createStartActivityOnClickListener(
                        item, TextClassification.createIntentOnClickListener(
                                mTextView.getContext(), textClassification.getIntent()));
            }
            final int count = textClassification.getSecondaryActionsCount();
            for (int i = 0; i < count; i++) {
                if (!isValidAssistMenuItem(
                final OnClickListener onClick1 = getSupportedOnClickListener(
                        textClassification.getSecondaryIcon(i),
                        textClassification.getSecondaryLabel(i),
                        textClassification.getSecondaryIntent(i))) {
                        textClassification.getSecondaryIntent(i));
                if (onClick1 == null) {
                    continue;
                }
                final int order = MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i;
@@ -4050,7 +4052,7 @@ public class Editor {
                        .setIntent(textClassification.getSecondaryIntent(i));
                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                mAssistClickHandlers.put(item,
                        TextClassification.createStartActivityOnClickListener(
                        TextClassification.createIntentOnClickListener(
                                mTextView.getContext(), textClassification.getSecondaryIntent(i)));
            }
        }
@@ -4067,30 +4069,15 @@ public class Editor {
            }
        }

        private boolean isValidAssistMenuItem(Drawable icon, CharSequence label, Intent intent) {
        @Nullable
        private OnClickListener getSupportedOnClickListener(
                Drawable icon, CharSequence label, Intent intent) {
            final boolean hasUi = icon != null || !TextUtils.isEmpty(label);
            final boolean hasAction = isSupportedIntent(intent);
            return hasUi && hasAction;
        }

        private boolean isSupportedIntent(Intent intent) {
            if (intent == null) {
                return false;
            }
            final Context context = mTextView.getContext();
            final ResolveInfo info = context.getPackageManager().resolveActivity(intent, 0);
            final boolean samePackage = context.getPackageName().equals(
                    info.activityInfo.packageName);
            if (samePackage) {
                return true;
            if (hasUi) {
                return TextClassification.createIntentOnClickListener(
                        mTextView.getContext(), intent);
            }

            final boolean exported =  info.activityInfo.exported;
            final boolean requiresPermission = info.activityInfo.permission != null;
            final boolean hasPermission = !requiresPermission
                    || context.checkSelfPermission(info.activityInfo.permission)
                            == PackageManager.PERMISSION_GRANTED;
            return exported && hasPermission;
            return null;
        }

        private boolean onAssistMenuItemClicked(MenuItem assistMenuItem) {
@@ -4107,7 +4094,7 @@ public class Editor {
            if (onClickListener == null) {
                final Intent intent = assistMenuItem.getIntent();
                if (intent != null) {
                    onClickListener = TextClassification.createStartActivityOnClickListener(
                    onClickListener = TextClassification.createIntentOnClickListener(
                            mTextView.getContext(), intent);
                }
            }