diff options
| author | 2019-06-05 11:53:28 +0100 | |
|---|---|---|
| committer | 2019-06-05 12:52:22 +0100 | |
| commit | 82e60027f452d2b36ce9d405a3b8e37aa0592857 (patch) | |
| tree | 1ce681737b5c2ef4321ae7a0bc7e7e353c0eba3c | |
| parent | f61e5f24100ca5bd0606a4e628ad8fbe3723b9c2 (diff) | |
Fix an issue that clicking on a smart action chip on keyguard ...
failed to launch app resolver when there are more than one app handlers.
What happened:
1. TextClassifier constructs an implicit intent to fulfill a task
like opening a link, making a phone call, etc.
2. TextClassifier calls resolveActivity against the implicit intent to
resolve the intent. The resolve component name will be used to create
an explicit intent. In this case, the intent is resolved to the
app resolver activity.
3. wouldLaunchResolverActivity in SysUI returns false for an explicit
intent with component name android/ResolverActivity.
4. SysUI does not trigger the "start the activity after the keyguard
is gone" logic because wouldLaunchResolverActivity returns false.
5. When user clicks on the action on keyguard, ResolveActivity.onStop
is triggered because it is shown (and thus moved to the background)
under the keyguard. So, finish() is called in onStop, and thus the bug.
IMHO, wouldLaunchResolverActivity should not return false
for an explicit intent with component name android/ResolverActivity.
But since we are late at this point, the safest option is to not setting
component name when the intent is resolved to package "android". Note that
this is what we are doing for P, so it should be pretty safe.
Test: 1. Install two browsers. Send myself a link. Tap on the Open Link
chip on keyguard. App resolver is shown.
2. atest frameworks/base/core/tests/coretests/src/android/view/textclassifier/
BUG: 129220155
Change-Id: I6d4d67c2233a2fec950887ea274825bf1cbc1ae2
3 files changed, 41 insertions, 5 deletions
diff --git a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java index 9c268f2d18a8..3ed48f655d47 100644 --- a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java +++ b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java @@ -19,7 +19,9 @@ package android.view.textclassifier; import android.annotation.Nullable; import android.app.Person; import android.app.RemoteAction; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Pair; @@ -200,10 +202,12 @@ public final class ActionsSuggestionsHelper { if (remoteAction == null) { return null; } + Intent actionIntent = ExtrasUtils.getActionIntent(conversationAction.getExtras()); + ComponentName componentName = actionIntent.getComponent(); + // Action without a component name will be considered as from the same app. + String packageName = componentName == null ? null : componentName.getPackageName(); return new Pair<>( - conversationAction.getAction().getTitle().toString(), - ExtrasUtils.getActionIntent( - conversationAction.getExtras()).getComponent().getPackageName()); + conversationAction.getAction().getTitle().toString(), packageName); } private static final class PersonEncoder { diff --git a/core/java/android/view/textclassifier/intent/LabeledIntent.java b/core/java/android/view/textclassifier/intent/LabeledIntent.java index b4bc8d39d562..30fc20ea86a1 100644 --- a/core/java/android/view/textclassifier/intent/LabeledIntent.java +++ b/core/java/android/view/textclassifier/intent/LabeledIntent.java @@ -118,14 +118,16 @@ public final class LabeledIntent { return null; } Intent resolvedIntent = new Intent(intent); - resolvedIntent.setComponent(new ComponentName(packageName, className)); resolvedIntent.putExtra( TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER, getFromTextClassifierExtra(textLanguagesBundle)); - boolean shouldShowIcon = false; Icon icon = null; if (!"android".equals(packageName)) { + // We only set the component name when the package name is not resolved to "android" + // to workaround a bug that explicit intent with component name == ResolverActivity + // can't be launched on keyguard. + resolvedIntent.setComponent(new ComponentName(packageName, className)); if (resolveInfo.activityInfo.getIconResource() != 0) { icon = Icon.createWithResource( packageName, resolveInfo.activityInfo.getIconResource()); diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java index db5f82a0a373..80bce264c11b 100644 --- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java @@ -208,6 +208,36 @@ public class ActionsSuggestionsHelperTest { assertThat(conversationActions.get(2).getAction()).isNull(); } + @Test + public void testDeduplicateActions_nullComponent() { + Bundle phoneExtras = new Bundle(); + Intent phoneIntent = new Intent(Intent.ACTION_DIAL); + ExtrasUtils.putActionIntent(phoneExtras, phoneIntent); + PendingIntent pendingIntent = PendingIntent.getActivity( + InstrumentationRegistry.getTargetContext(), + 0, + phoneIntent, + 0); + Icon icon = Icon.createWithData(new byte[0], 0, 0); + ConversationAction action = + new ConversationAction.Builder(ConversationAction.TYPE_CALL_PHONE) + .setAction(new RemoteAction(icon, "label", "1", pendingIntent)) + .setExtras(phoneExtras) + .build(); + ConversationAction actionWithSameLabel = + new ConversationAction.Builder(ConversationAction.TYPE_CALL_PHONE) + .setAction(new RemoteAction( + icon, "label", "2", pendingIntent)) + .setExtras(phoneExtras) + .build(); + + List<ConversationAction> conversationActions = + ActionsSuggestionsHelper.removeActionsWithDuplicates( + Arrays.asList(action, actionWithSameLabel)); + + assertThat(conversationActions).isEmpty(); + } + public void createLabeledIntentResult_null() { ActionsSuggestionsModel.ActionSuggestion nativeSuggestion = new ActionsSuggestionsModel.ActionSuggestion( |