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

This commit is contained in:
Abodunrinwa Toki
2018-04-27 19:44:48 +00:00
committed by Android (Google) Code Review
4 changed files with 77 additions and 8 deletions

View File

@@ -55,7 +55,8 @@ public final class SystemTextClassifier implements TextClassifier {
mManagerService = ITextClassifierService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE));
mSettings = Preconditions.checkNotNull(settings);
mFallback = new TextClassifierImpl(context, settings);
mFallback = context.getSystemService(TextClassificationManager.class)
.getTextClassifier(TextClassifier.LOCAL);
mPackageName = Preconditions.checkNotNull(context.getPackageName());
}

View File

@@ -191,10 +191,11 @@ public final class TextClassificationManager {
synchronized (mLock) {
if (mLocalTextClassifier == null) {
if (mSettings.isLocalTextClassifierEnabled()) {
mLocalTextClassifier = new TextClassifierImpl(mContext, mSettings);
mLocalTextClassifier =
new TextClassifierImpl(mContext, mSettings, TextClassifier.NO_OP);
} else {
Log.d(LOG_TAG, "Local TextClassifier disabled");
mLocalTextClassifier = TextClassifierImpl.NO_OP;
mLocalTextClassifier = TextClassifier.NO_OP;
}
}
return mLocalTextClassifier;

View File

@@ -21,6 +21,7 @@ import static java.time.temporal.ChronoUnit.MILLIS;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.SearchManager;
import android.content.ComponentName;
@@ -98,13 +99,18 @@ public final class TextClassifierImpl implements TextClassifier {
private final TextClassificationConstants mSettings;
public TextClassifierImpl(Context context, TextClassificationConstants settings) {
public TextClassifierImpl(
Context context, TextClassificationConstants settings, TextClassifier fallback) {
mContext = Preconditions.checkNotNull(context);
mFallback = TextClassifier.NO_OP;
mFallback = Preconditions.checkNotNull(fallback);
mSettings = Preconditions.checkNotNull(settings);
mGenerateLinksLogger = new GenerateLinksLogger(mSettings.getGenerateLinksLogSampleRate());
}
public TextClassifierImpl(Context context, TextClassificationConstants settings) {
this(context, settings, TextClassifier.NO_OP);
}
/** @inheritDoc */
@Override
@WorkerThread
@@ -413,6 +419,9 @@ public final class TextClassifierImpl implements TextClassifier {
for (LabeledIntent labeledIntent : IntentFactory.create(
mContext, referenceTime, highestScoringResult, classifiedText)) {
final RemoteAction action = labeledIntent.asRemoteAction(mContext);
if (action == null) {
continue;
}
if (isPrimaryAction) {
// For O backwards compatibility, the first RemoteAction is also written to the
// legacy API fields.
@@ -601,6 +610,7 @@ public final class TextClassifierImpl implements TextClassifier {
return mRequestCode;
}
@Nullable
RemoteAction asRemoteAction(Context context) {
final PackageManager pm = context.getPackageManager();
final ResolveInfo resolveInfo = pm.resolveActivity(mIntent, 0);
@@ -622,8 +632,12 @@ public final class TextClassifierImpl implements TextClassifier {
icon = Icon.createWithResource("android",
com.android.internal.R.drawable.ic_more_items);
}
final RemoteAction action = new RemoteAction(icon, mTitle, mDescription,
TextClassification.createPendingIntent(context, mIntent, mRequestCode));
final PendingIntent pendingIntent =
TextClassification.createPendingIntent(context, mIntent, mRequestCode);
if (pendingIntent == null) {
return null;
}
final RemoteAction action = new RemoteAction(icon, mTitle, mDescription, pendingIntent);
action.setShouldShowIcon(shouldShowIcon);
return action;
}

View File

@@ -18,11 +18,22 @@ package android.view.textclassifier;
import static org.hamcrest.CoreMatchers.not;
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.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.when;
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.service.textclassifier.TextClassifierService;
import android.support.test.InstrumentationRegistry;
@@ -35,6 +46,7 @@ import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import java.util.Arrays;
import java.util.Collections;
@@ -305,7 +317,6 @@ public class TextClassificationManagerTest {
public void testGetLocalTextClassifier() {
assertTrue(mTcm.getTextClassifier(TextClassifier.LOCAL) instanceof TextClassifierImpl);
}
@Test
public void testGetSystemTextClassifier() {
assertTrue(
@@ -313,6 +324,48 @@ public class TextClassificationManagerTest {
|| 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() {
return mClassifier == TextClassifier.NO_OP;
}