diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java index 4b0ab59a931c6..b54d7e201c850 100644 --- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java +++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java @@ -106,11 +106,11 @@ public class SuggestionParser { public SuggestionParser( Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) { - mContext = context; - mSuggestionList = (List) new SuggestionOrderInflater(mContext) - .parse(orderXml); - mSharedPrefs = sharedPrefs; - mSmartDismissControl = smartDismissControl; + this( + context, + sharedPrefs, + (List) new SuggestionOrderInflater(context).parse(orderXml), + smartDismissControl); } public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) { @@ -118,12 +118,15 @@ public class SuggestionParser { } @VisibleForTesting - public SuggestionParser(Context context, SharedPreferences sharedPrefs) { + public SuggestionParser( + Context context, + SharedPreferences sharedPrefs, + List suggestionList, + String smartDismissControl) { mContext = context; - mSuggestionList = new ArrayList(); + mSuggestionList = suggestionList; mSharedPrefs = sharedPrefs; - mSmartDismissControl = DEFAULT_SMART_DISMISS_CONTROL; - Log.wtf(TAG, "Only use this constructor for testing"); + mSmartDismissControl = smartDismissControl; } public List getSuggestions() { @@ -134,7 +137,19 @@ public class SuggestionParser { List suggestions = new ArrayList<>(); final int N = mSuggestionList.size(); for (int i = 0; i < N; i++) { - readSuggestions(mSuggestionList.get(i), suggestions, isSmartSuggestionEnabled); + final SuggestionCategory category = mSuggestionList.get(i); + if (category.exclusive) { + // If suggestions from an exclusive category are present, parsing is stopped + // and only suggestions from that category are displayed. Note that subsequent + // exclusive categories are also ignored. + List exclusiveSuggestions = new ArrayList<>(); + readSuggestions(category, exclusiveSuggestions, isSmartSuggestionEnabled); + if (!exclusiveSuggestions.isEmpty()) { + return exclusiveSuggestions; + } + } else { + readSuggestions(category, suggestions, isSmartSuggestionEnabled); + } } return suggestions; } @@ -368,6 +383,7 @@ public class SuggestionParser { public String category; public String pkg; public boolean multiple; + public boolean exclusive; } private static class SuggestionOrderInflater { @@ -377,6 +393,7 @@ public class SuggestionParser { private static final String ATTR_CATEGORY = "category"; private static final String ATTR_PACKAGE = "package"; private static final String ATTR_MULTIPLE = "multiple"; + private static final String ATTR_EXCLUSIVE = "exclusive"; private final Context mContext; @@ -451,6 +468,9 @@ public class SuggestionParser { category.pkg = attrs.getAttributeValue(null, ATTR_PACKAGE); String multiple = attrs.getAttributeValue(null, ATTR_MULTIPLE); category.multiple = !TextUtils.isEmpty(multiple) && Boolean.parseBoolean(multiple); + String exclusive = attrs.getAttributeValue(null, ATTR_EXCLUSIVE); + category.exclusive = + !TextUtils.isEmpty(exclusive) && Boolean.parseBoolean(exclusive); return category; } else { throw new IllegalArgumentException("Unknown item " + name); diff --git a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml index 1eeafba1bf8f5..0e2ce3be55eb7 100644 --- a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml +++ b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml @@ -15,6 +15,8 @@ --> + mSuggestionsBeforeDismiss; private List mSuggestionsAfterDismiss; private SharedPreferences mPrefs; private Tile mSuggestion; - private List mInfo; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - when(mContext.getPackageManager()).thenReturn(mPackageManager); + RuntimeEnvironment.setRobolectricPackageManager( + new TestPackageManager(RuntimeEnvironment.getAppResourceLoader())); + mContext = RuntimeEnvironment.application; mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); mSuggestion = new Tile(); mSuggestion.intent = new Intent("action"); mSuggestion.intent.setComponent(new ComponentName("pkg", "cls")); mSuggestion.metaData = new Bundle(); + mMultipleCategory = new SuggestionParser.SuggestionCategory(); + mMultipleCategory.category = "category1"; + mMultipleCategory.multiple = true; + mExclusiveCategory = new SuggestionParser.SuggestionCategory(); + mExclusiveCategory.category = "category2"; + mExclusiveCategory.exclusive = true; mSuggestionParser = new SuggestionParser( - mContext, mPrefs, R.xml.suggestion_ordering, "0,0"); - mSuggestioCategory = new SuggestionParser.SuggestionCategory(); - mSuggestioCategory.category = "category1"; - mSuggestioCategory.multiple = true; - mInfo = new ArrayList<>(); + mContext, mPrefs, Arrays.asList(mMultipleCategory, mExclusiveCategory), "0,0"); + ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1"); info1.activityInfo.packageName = "pkg"; ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1"); info2.activityInfo.packageName = "pkg2"; - mInfo.add(info1); - mInfo.add(info2); - when(mPackageManager.queryIntentActivitiesAsUser( - any(Intent.class), anyInt(), anyInt())).thenReturn(mInfo); + ResolveInfo info3 = TileUtilsTest.newInfo(true, "category2"); + info3.activityInfo.packageName = "pkg3"; + + Intent intent1 = new Intent(Intent.ACTION_MAIN).addCategory("category1"); + Intent intent2 = new Intent(Intent.ACTION_MAIN).addCategory("category2"); + RuntimeEnvironment.getRobolectricPackageManager().addResolveInfoForIntent(intent1, info1); + RuntimeEnvironment.getRobolectricPackageManager().addResolveInfoForIntent(intent1, info2); + RuntimeEnvironment.getRobolectricPackageManager().addResolveInfoForIntent(intent2, info3); } @Test @@ -99,30 +100,64 @@ public class SuggestionParserTest { @Test public void testGetSuggestions_withoutSmartSuggestions() { readAndDismissSuggestion(false); - mSuggestionParser.readSuggestions(mSuggestioCategory, mSuggestionsAfterDismiss, false); - assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2); - assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(1); + mSuggestionParser.readSuggestions(mMultipleCategory, mSuggestionsAfterDismiss, false); + assertThat(mSuggestionsBeforeDismiss).hasSize(2); + assertThat(mSuggestionsAfterDismiss).hasSize(1); assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0)); } @Test public void testGetSuggestions_withSmartSuggestions() { readAndDismissSuggestion(true); - assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2); - assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(2); + assertThat(mSuggestionsBeforeDismiss).hasSize(2); + assertThat(mSuggestionsAfterDismiss).hasSize(2); assertThat(mSuggestionsBeforeDismiss).isEqualTo(mSuggestionsAfterDismiss); } + @Test + public void testGetSuggestion_exclusiveNotAvailable() { + RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent( + new Intent(Intent.ACTION_MAIN).addCategory("category2"), + "pkg3"); + + // If exclusive item is not available, the other categories should be shown + final List suggestions = mSuggestionParser.getSuggestions(); + assertThat(suggestions).hasSize(2); + assertThat(suggestions.get(0).category).isEqualTo("category1"); + assertThat(suggestions.get(1).category).isEqualTo("category1"); + } + + @Test + public void testGetSuggestions_exclusive() { + final List suggestions = mSuggestionParser.getSuggestions(); + assertThat(suggestions).hasSize(1); + assertThat(suggestions.get(0).category).isEqualTo("category2"); + } + private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) { - mSuggestionsBeforeDismiss = new ArrayList(); - mSuggestionsAfterDismiss = new ArrayList(); + mSuggestionsBeforeDismiss = new ArrayList<>(); + mSuggestionsAfterDismiss = new ArrayList<>(); mSuggestionParser.readSuggestions( - mSuggestioCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled); - if (mSuggestionParser.dismissSuggestion( - mSuggestionsBeforeDismiss.get(0), isSmartSuggestionEnabled)) { - mInfo.remove(0); + mMultipleCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled); + final Tile suggestion = mSuggestionsBeforeDismiss.get(0); + if (mSuggestionParser.dismissSuggestion(suggestion, isSmartSuggestionEnabled)) { + RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent( + new Intent(Intent.ACTION_MAIN).addCategory(suggestion.category), + suggestion.intent.getComponent().getPackageName()); } mSuggestionParser.readSuggestions( - mSuggestioCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled); + mMultipleCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled); + } + + private static class TestPackageManager extends DefaultPackageManager { + + TestPackageManager(ResourceLoader appResourceLoader) { + super(appResourceLoader); + } + + @Override + public List queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { + return super.queryIntentActivities(intent, flags); + } } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 2d3c4a786f5c8..dfbe43bc39341 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -16,11 +16,22 @@ package com.android.settingslib.drawer; -import android.app.ActivityManager; +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import android.content.IContentProvider; +import static org.mockito.Mockito.when; + +import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; +import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -40,34 +51,23 @@ import android.util.Pair; import com.android.settingslib.SuggestionParser; import com.android.settingslib.TestConfig; -import com.android.settingslib.drawer.TileUtilsTest; -import static org.mockito.Mockito.atLeastOnce; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.shadows.ShadowApplication; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; -import org.mockito.ArgumentCaptor; - @RunWith(RobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -179,7 +179,11 @@ public class TileUtilsTest { false /* checkCategory */); assertThat(outTiles.size()).isEqualTo(1); - SuggestionParser parser = new SuggestionParser(mContext, null); + SuggestionParser parser = new SuggestionParser( + mContext, + null, + Collections.emptyList(), + "0,10"); parser.filterSuggestions(outTiles, 0, false); assertThat(outTiles.size()).isEqualTo(0); }