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