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

Commit 453c1225 authored by Abodunrinwa Toki's avatar Abodunrinwa Toki Committed by android-build-merger
Browse files

Merge "TC: Fix null PendingIntent being passed to RemoteAction" into pi-dev

am: 12902265

Change-Id: I2d55563201f7101c57e1f3091644130745c87ce4
parents e0c8f4ab 12902265
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -55,7 +55,8 @@ public final class SystemTextClassifier implements TextClassifier {
        mManagerService = ITextClassifierService.Stub.asInterface(
        mManagerService = ITextClassifierService.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE));
                ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE));
        mSettings = Preconditions.checkNotNull(settings);
        mSettings = Preconditions.checkNotNull(settings);
        mFallback = new TextClassifierImpl(context, settings);
        mFallback = context.getSystemService(TextClassificationManager.class)
                .getTextClassifier(TextClassifier.LOCAL);
        mPackageName = Preconditions.checkNotNull(context.getPackageName());
        mPackageName = Preconditions.checkNotNull(context.getPackageName());
    }
    }


+3 −2
Original line number Original line Diff line number Diff line
@@ -191,10 +191,11 @@ public final class TextClassificationManager {
        synchronized (mLock) {
        synchronized (mLock) {
            if (mLocalTextClassifier == null) {
            if (mLocalTextClassifier == null) {
                if (mSettings.isLocalTextClassifierEnabled()) {
                if (mSettings.isLocalTextClassifierEnabled()) {
                    mLocalTextClassifier = new TextClassifierImpl(mContext, mSettings);
                    mLocalTextClassifier =
                            new TextClassifierImpl(mContext, mSettings, TextClassifier.NO_OP);
                } else {
                } else {
                    Log.d(LOG_TAG, "Local TextClassifier disabled");
                    Log.d(LOG_TAG, "Local TextClassifier disabled");
                    mLocalTextClassifier = TextClassifierImpl.NO_OP;
                    mLocalTextClassifier = TextClassifier.NO_OP;
                }
                }
            }
            }
            return mLocalTextClassifier;
            return mLocalTextClassifier;
+18 −4
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static java.time.temporal.ChronoUnit.MILLIS;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.annotation.WorkerThread;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.RemoteAction;
import android.app.SearchManager;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.ComponentName;
@@ -98,13 +99,18 @@ public final class TextClassifierImpl implements TextClassifier {


    private final TextClassificationConstants mSettings;
    private final TextClassificationConstants mSettings;


    public TextClassifierImpl(Context context, TextClassificationConstants settings) {
    public TextClassifierImpl(
            Context context, TextClassificationConstants settings, TextClassifier fallback) {
        mContext = Preconditions.checkNotNull(context);
        mContext = Preconditions.checkNotNull(context);
        mFallback = TextClassifier.NO_OP;
        mFallback = Preconditions.checkNotNull(fallback);
        mSettings = Preconditions.checkNotNull(settings);
        mSettings = Preconditions.checkNotNull(settings);
        mGenerateLinksLogger = new GenerateLinksLogger(mSettings.getGenerateLinksLogSampleRate());
        mGenerateLinksLogger = new GenerateLinksLogger(mSettings.getGenerateLinksLogSampleRate());
    }
    }


    public TextClassifierImpl(Context context, TextClassificationConstants settings) {
        this(context, settings, TextClassifier.NO_OP);
    }

    /** @inheritDoc */
    /** @inheritDoc */
    @Override
    @Override
    @WorkerThread
    @WorkerThread
@@ -413,6 +419,9 @@ public final class TextClassifierImpl implements TextClassifier {
        for (LabeledIntent labeledIntent : IntentFactory.create(
        for (LabeledIntent labeledIntent : IntentFactory.create(
                mContext, referenceTime, highestScoringResult, classifiedText)) {
                mContext, referenceTime, highestScoringResult, classifiedText)) {
            final RemoteAction action = labeledIntent.asRemoteAction(mContext);
            final RemoteAction action = labeledIntent.asRemoteAction(mContext);
            if (action == null) {
                continue;
            }
            if (isPrimaryAction) {
            if (isPrimaryAction) {
                // For O backwards compatibility, the first RemoteAction is also written to the
                // For O backwards compatibility, the first RemoteAction is also written to the
                // legacy API fields.
                // legacy API fields.
@@ -601,6 +610,7 @@ public final class TextClassifierImpl implements TextClassifier {
            return mRequestCode;
            return mRequestCode;
        }
        }


        @Nullable
        RemoteAction asRemoteAction(Context context) {
        RemoteAction asRemoteAction(Context context) {
            final PackageManager pm = context.getPackageManager();
            final PackageManager pm = context.getPackageManager();
            final ResolveInfo resolveInfo = pm.resolveActivity(mIntent, 0);
            final ResolveInfo resolveInfo = pm.resolveActivity(mIntent, 0);
@@ -622,8 +632,12 @@ public final class TextClassifierImpl implements TextClassifier {
                icon = Icon.createWithResource("android",
                icon = Icon.createWithResource("android",
                        com.android.internal.R.drawable.ic_more_items);
                        com.android.internal.R.drawable.ic_more_items);
            }
            }
            final RemoteAction action = new RemoteAction(icon, mTitle, mDescription,
            final PendingIntent pendingIntent =
                    TextClassification.createPendingIntent(context, mIntent, mRequestCode));
                    TextClassification.createPendingIntent(context, mIntent, mRequestCode);
            if (pendingIntent == null) {
                return null;
            }
            final RemoteAction action = new RemoteAction(icon, mTitle, mDescription, pendingIntent);
            action.setShouldShowIcon(shouldShowIcon);
            action.setShouldShowIcon(shouldShowIcon);
            return action;
            return action;
        }
        }
+54 −1
Original line number Original line Diff line number Diff line
@@ -18,11 +18,22 @@ package android.view.textclassifier;


import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


import android.content.Context;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.LocaleList;
import android.os.LocaleList;
import android.service.textclassifier.TextClassifierService;
import android.service.textclassifier.TextClassifierService;
import android.support.test.InstrumentationRegistry;
import android.support.test.InstrumentationRegistry;
@@ -35,6 +46,7 @@ import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;


import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
@@ -305,7 +317,6 @@ public class TextClassificationManagerTest {
    public void testGetLocalTextClassifier() {
    public void testGetLocalTextClassifier() {
        assertTrue(mTcm.getTextClassifier(TextClassifier.LOCAL) instanceof TextClassifierImpl);
        assertTrue(mTcm.getTextClassifier(TextClassifier.LOCAL) instanceof TextClassifierImpl);
    }
    }

    @Test
    @Test
    public void testGetSystemTextClassifier() {
    public void testGetSystemTextClassifier() {
        assertTrue(
        assertTrue(
@@ -313,6 +324,48 @@ public class TextClassificationManagerTest {
                || mTcm.getTextClassifier(TextClassifier.SYSTEM) instanceof SystemTextClassifier);
                || mTcm.getTextClassifier(TextClassifier.SYSTEM) instanceof SystemTextClassifier);
    }
    }


    @Test
    public void testCannotResolveIntent() {
        final PackageManager fakePackageMgr = mock(PackageManager.class);

        ResolveInfo validInfo = mContext.getPackageManager().resolveActivity(
                new Intent(Intent.ACTION_DIAL).setData(Uri.parse("tel:+12122537077")), 0);
        // Make packageManager fail when it gets the following intent:
        ArgumentMatcher<Intent> toFailIntent =
                intent -> intent.getAction().equals(Intent.ACTION_INSERT_OR_EDIT);

        when(fakePackageMgr.resolveActivity(any(Intent.class), anyInt())).thenReturn(validInfo);
        when(fakePackageMgr.resolveActivity(argThat(toFailIntent), anyInt())).thenReturn(null);

        ContextWrapper fakeContext = new ContextWrapper(mContext) {
            @Override
            public PackageManager getPackageManager() {
                return fakePackageMgr;
            }
        };

        TextClassifier fallback = TextClassifier.NO_OP;
        TextClassifier classifier = new TextClassifierImpl(
                fakeContext, TextClassificationConstants.loadFromString(null), fallback);

        String text = "Contact me at +12122537077";
        String classifiedText = "+12122537077";
        int startIndex = text.indexOf(classifiedText);
        int endIndex = startIndex + classifiedText.length();
        TextClassification.Request request = new TextClassification.Request.Builder(
                text, startIndex, endIndex)
                .setDefaultLocales(LOCALES)
                .build();

        TextClassification result = classifier.classifyText(request);
        TextClassification fallbackResult = fallback.classifyText(request);

        // classifier should not totally fail in which case it returns a fallback result.
        // It should skip the failing intent and return a result for non-failing intents.
        assertFalse(result.getActions().isEmpty());
        assertNotSame(result, fallbackResult);
    }

    private boolean isTextClassifierDisabled() {
    private boolean isTextClassifierDisabled() {
        return mClassifier == TextClassifier.NO_OP;
        return mClassifier == TextClassifier.NO_OP;
    }
    }