From 5651e0f2ce643af912fabb5e0ffcf0d0275bc4f2 Mon Sep 17 00:00:00 2001 From: Tony Mak Date: Mon, 12 Jun 2017 18:31:40 +0100 Subject: [PATCH] Fix searching work app in settings NO PARTIAL RERUN Test: m -j RunSettingsRoboTests Test: Observe search result with badged icon and showing work app info when tapping on it. Test: personal app search result is still working Test: Non app search result is working Fix: 62366873 Merged-in: I333372699b263d02cc4083289dc746c7aacd414d Change-Id: I9c87345478f8df57b151927d8097cd8fd90fbe79 --- .../settings/search2/AppSearchResult.java | 5 ++ .../search2/IntentSearchViewHolder.java | 10 ++- .../settings/search2/SearchViewHolder.java | 12 ++- .../search/IntentSearchViewHolderTest.java | 73 +++++++++++++++++-- 4 files changed, 92 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/search2/AppSearchResult.java b/src/com/android/settings/search2/AppSearchResult.java index 111f7756a49..eeccb82d638 100644 --- a/src/com/android/settings/search2/AppSearchResult.java +++ b/src/com/android/settings/search2/AppSearchResult.java @@ -18,6 +18,7 @@ package com.android.settings.search2; import android.content.pm.ApplicationInfo; +import android.os.UserHandle; public class AppSearchResult extends SearchResult { /** @@ -30,6 +31,10 @@ public class AppSearchResult extends SearchResult { info = builder.mInfo; } + public UserHandle getAppUserHandle() { + return new UserHandle(UserHandle.getUserId(info.uid)); + } + public static class Builder extends SearchResult.Builder { protected ApplicationInfo mInfo; diff --git a/src/com/android/settings/search2/IntentSearchViewHolder.java b/src/com/android/settings/search2/IntentSearchViewHolder.java index f0cbc51391d..9a7e395bb20 100644 --- a/src/com/android/settings/search2/IntentSearchViewHolder.java +++ b/src/com/android/settings/search2/IntentSearchViewHolder.java @@ -17,6 +17,7 @@ package com.android.settings.search2; import android.content.ComponentName; import android.content.Intent; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Pair; import android.view.View; @@ -51,7 +52,14 @@ public class IntentSearchViewHolder extends SearchViewHolder { mMetricsFeatureProvider.action(v.getContext(), MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT, resultName, rank); - fragment.startActivity(intent); + // Use app user id to support work profile use case. + if (result instanceof AppSearchResult) { + AppSearchResult appResult = (AppSearchResult) result; + UserHandle userHandle = appResult.getAppUserHandle(); + fragment.getActivity().startActivityAsUser(intent, userHandle); + } else { + fragment.startActivity(intent); + } }); } } diff --git a/src/com/android/settings/search2/SearchViewHolder.java b/src/com/android/settings/search2/SearchViewHolder.java index ab13252b9cc..185a5fe432e 100644 --- a/src/com/android/settings/search2/SearchViewHolder.java +++ b/src/com/android/settings/search2/SearchViewHolder.java @@ -17,8 +17,11 @@ package com.android.settings.search2; import android.content.Context; import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.UserHandle; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; +import android.util.IconDrawableFactory; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -44,6 +47,7 @@ public abstract class SearchViewHolder extends RecyclerView.ViewHolder { public final ImageView iconView; protected final MetricsFeatureProvider mMetricsFeatureProvider; + private final IconDrawableFactory mIconDrawableFactory; public SearchViewHolder(View view) { super(view); @@ -55,6 +59,7 @@ public abstract class SearchViewHolder extends RecyclerView.ViewHolder { breadcrumbView = view.findViewById(R.id.breadcrumb); mPlaceholderSummary = view.getContext().getString(R.string.summary_placeholder); + mIconDrawableFactory = IconDrawableFactory.newInstance(view.getContext()); } public void onBind(SearchFragment fragment, SearchResult result) { @@ -72,7 +77,12 @@ public abstract class SearchViewHolder extends RecyclerView.ViewHolder { if (result instanceof AppSearchResult) { AppSearchResult appResult = (AppSearchResult) result; PackageManager pm = fragment.getActivity().getPackageManager(); - iconView.setImageDrawable(appResult.info.loadIcon(pm)); + UserHandle userHandle = appResult.getAppUserHandle(); + Drawable badgedIcon = + mIconDrawableFactory.getBadgedIcon(appResult.info, userHandle.getIdentifier()); + iconView.setImageDrawable(badgedIcon); + titleView.setContentDescription( + pm.getUserBadgedLabel(appResult.info.loadLabel(pm), userHandle)); } else { // Valid even when result.icon is null. iconView.setImageDrawable(result.icon); diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java index 404a824463c..39da7180a56 100644 --- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java +++ b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java @@ -17,10 +17,22 @@ 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.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.os.UserHandle; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -29,6 +41,7 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.AppSearchResult; import com.android.settings.search2.IntentPayload; import com.android.settings.search2.IntentSearchViewHolder; import com.android.settings.search2.SearchFragment; @@ -48,25 +61,25 @@ import org.robolectric.annotation.Config; import java.util.ArrayList; import java.util.List; -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.verify; - @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class IntentSearchViewHolderTest { private static final String TITLE = "title"; private static final String SUMMARY = "summary"; + private static final int USER_ID = 10; + private static final String BADGED_LABEL = "work title"; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private SearchFragment mFragment; + @Mock + private PackageManager mPackageManager; private FakeFeatureFactory mFeatureFactory; private IntentSearchViewHolder mHolder; private Drawable mIcon; + private Drawable mBadgedIcon; @Before public void setUp() { @@ -79,6 +92,8 @@ public class IntentSearchViewHolderTest { mHolder = new IntentSearchViewHolder(view); mIcon = context.getDrawable(R.drawable.ic_search_history); + mBadgedIcon = context.getDrawable(R.drawable.ic_add); + when(mFragment.getActivity().getPackageManager()).thenReturn(mPackageManager); } @Test @@ -177,6 +192,30 @@ public class IntentSearchViewHolderTest { assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); } + public void testBindViewElements_appSearchResult() { + when(mPackageManager.getUserBadgedLabel(any(CharSequence.class), + eq(new UserHandle(USER_ID)))).thenReturn(BADGED_LABEL); + + SearchResult result = getAppSearchResult( + TITLE, SUMMARY, mIcon, getApplicationInfo(USER_ID, TITLE, mIcon)); + 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); + assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE); + assertThat(mHolder.titleView.getContentDescription()).isEqualTo(BADGED_LABEL); + + verify(mFragment).onSearchResultClicked(); + verify(mFragment.getActivity()).startActivityAsUser( + any(Intent.class), eq(new UserHandle(USER_ID))); + verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class), + eq(MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT), + eq(((IntentPayload)result.payload).intent.getComponent().flattenToString()), + any(Pair.class)); + } + private SearchResult getSearchResult(String title, String summary, Drawable icon) { Builder builder = new Builder(); builder.addTitle(title) @@ -189,4 +228,26 @@ public class IntentSearchViewHolderTest { return builder.build(); } + + private SearchResult getAppSearchResult( + String title, String summary, Drawable icon, ApplicationInfo applicationInfo) { + AppSearchResult.Builder builder = new AppSearchResult.Builder(); + builder.addTitle(title) + .addSummary(summary) + .addRank(1) + .addPayload(new IntentPayload( + new Intent().setComponent(new ComponentName("pkg", "class")))) + .addBreadcrumbs(new ArrayList<>()) + .addIcon(icon); + builder.setAppInfo(applicationInfo); + return builder.build(); + } + + private ApplicationInfo getApplicationInfo(int userId, CharSequence appLabel, Drawable icon) { + ApplicationInfo applicationInfo = spy(new ApplicationInfo()); + applicationInfo.uid = UserHandle.getUid(userId, 12345); + doReturn(icon).when(applicationInfo).loadIcon(any(PackageManager.class)); + doReturn(appLabel).when(applicationInfo).loadLabel(any(PackageManager.class)); + return applicationInfo; + } }