Merge "Query search result intent before launching to avoid crash" into oc-dr1-dev
am: 9f93faf7ae
Change-Id: I596f52f4db123c3df485a1a194966771706650db
diff --git a/src/com/android/settings/search/IntentSearchViewHolder.java b/src/com/android/settings/search/IntentSearchViewHolder.java
index 2722d56..711d08e 100644
--- a/src/com/android/settings/search/IntentSearchViewHolder.java
+++ b/src/com/android/settings/search/IntentSearchViewHolder.java
@@ -17,17 +17,24 @@
package com.android.settings.search;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.UserHandle;
+import android.util.Log;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto;
+import java.util.List;
+
/**
* ViewHolder for intent based search results.
* The DatabaseResultLoader is the primary use case for this ViewHolder.
*/
public class IntentSearchViewHolder extends SearchViewHolder {
+ private static final String TAG = "IntentSearchViewHolder";
+
public IntentSearchViewHolder(View view) {
super(view);
}
@@ -42,7 +49,7 @@
super.onBind(fragment, result);
itemView.setOnClickListener(v -> {
- fragment.onSearchResultClicked(this, result);
+ fragment.onSearchResultClicked(this, result);
final Intent intent = result.payload.getIntent();
// Use app user id to support work profile use case.
if (result instanceof AppSearchResult) {
@@ -50,7 +57,14 @@
UserHandle userHandle = appResult.getAppUserHandle();
fragment.getActivity().startActivityAsUser(intent, userHandle);
} else {
- fragment.startActivity(intent);
+ final PackageManager pm = fragment.getActivity().getPackageManager();
+ final List<ResolveInfo> info = pm.queryIntentActivities(intent, 0 /* flags */);
+ if (info != null && !info.isEmpty()) {
+ fragment.startActivity(intent);
+ } else {
+ Log.e(TAG, "Cannot launch search result, title: "
+ + result.title + ", " + intent);
+ }
}
});
}
diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
index 38e6285..a3826f6 100644
--- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
+++ b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
@@ -18,10 +18,10 @@
package com.android.settings.search;
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,6 +31,7 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.view.LayoutInflater;
@@ -52,6 +53,7 @@
import org.robolectric.annotation.Config;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -82,7 +84,7 @@
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
final Context context = RuntimeEnvironment.application;
- View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null);
+ final View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null);
mHolder = new IntentSearchViewHolder(view);
mIcon = context.getDrawable(R.drawable.ic_search_24dp);
@@ -100,7 +102,7 @@
@Test
public void testBindViewElements_allUpdated() {
- SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon);
+ final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon);
mHolder.onBind(mFragment, result);
mHolder.itemView.performClick();
@@ -111,7 +113,6 @@
assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE);
verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class));
- verify(mFragment).startActivity(any(Intent.class));
}
@Test
@@ -158,8 +159,8 @@
@Test
public void testBindElements_placeholderSummary_visibilityIsGone() {
- String nonBreakingSpace = mContext.getString(R.string.summary_placeholder);
- SearchResult result = new Builder()
+ final String nonBreakingSpace = mContext.getString(R.string.summary_placeholder);
+ final SearchResult result = new Builder()
.setTitle(TITLE)
.setSummary(nonBreakingSpace)
.setPayload(new ResultPayload(null))
@@ -173,8 +174,8 @@
@Test
public void testBindElements_dynamicSummary_visibilityIsGone() {
- String dynamicSummary = "%s";
- SearchResult result = new Builder()
+ final String dynamicSummary = "%s";
+ final SearchResult result = new Builder()
.setTitle(TITLE)
.setSummary(dynamicSummary)
.setPayload(new ResultPayload(null))
@@ -191,7 +192,7 @@
when(mPackageManager.getUserBadgedLabel(any(CharSequence.class),
eq(new UserHandle(USER_ID)))).thenReturn(BADGED_LABEL);
- SearchResult result = getAppSearchResult(
+ final SearchResult result = getAppSearchResult(
TITLE, SUMMARY, mIcon, getApplicationInfo(USER_ID, TITLE, mIcon));
mHolder.onBind(mFragment, result);
mHolder.itemView.performClick();
@@ -207,6 +208,38 @@
any(Intent.class), eq(new UserHandle(USER_ID)));
}
+ @Test
+ public void testBindViewElements_validSubSettingIntent_shouldLaunch() {
+ final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon);
+ when(mPackageManager.queryIntentActivities(result.payload.getIntent(), 0 /* flags */))
+ .thenReturn(Arrays.asList(new ResolveInfo()));
+
+ mHolder.onBind(mFragment, result);
+ mHolder.itemView.performClick();
+
+ assertThat(mHolder.titleView.getText()).isEqualTo(TITLE);
+ assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY);
+ assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class));
+ verify(mFragment).startActivity(result.payload.getIntent());
+ }
+
+ @Test
+ public void testBindViewElements_invalidSubSettingIntent_shouldNotLaunchAnything() {
+ final SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon);
+ when(mPackageManager.queryIntentActivities(result.payload.getIntent(), 0 /* flags */))
+ .thenReturn(null);
+
+ mHolder.onBind(mFragment, result);
+ mHolder.itemView.performClick();
+
+ assertThat(mHolder.titleView.getText()).isEqualTo(TITLE);
+ assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY);
+ assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class));
+ verify(mFragment, never()).startActivity(any(Intent.class));
+ }
+
private SearchResult getSearchResult(String title, String summary, Drawable icon) {
Builder builder = new Builder();
builder.setStableId(Objects.hash(title, summary, icon))