Loading packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java +63 −9 Original line number Diff line number Diff line Loading @@ -32,20 +32,25 @@ import android.os.UserManager; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; import android.util.Xml; import android.view.InflateException; import com.android.settingslib.drawer.Tile; import com.android.settingslib.drawer.TileUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; public class SuggestionParser { Loading Loading @@ -104,8 +109,8 @@ public class SuggestionParser { private final String mSmartDismissControl; public SuggestionParser( Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) { public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) { this( context, sharedPrefs, Loading Loading @@ -138,19 +143,25 @@ public class SuggestionParser { final int N = mSuggestionList.size(); for (int i = 0; i < N; i++) { final SuggestionCategory category = mSuggestionList.get(i); if (category.exclusive) { if (category.exclusive && !isExclusiveCategoryExpired(category)) { // 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<Tile> exclusiveSuggestions = new ArrayList<>(); readSuggestions(category, exclusiveSuggestions, isSmartSuggestionEnabled); final List<Tile> exclusiveSuggestions = new ArrayList<>(); // Read suggestion and force isSmartSuggestion to be false so the rule defined // from each suggestion itself is used. readSuggestions(category, exclusiveSuggestions, false /* isSmartSuggestion */); if (!exclusiveSuggestions.isEmpty()) { return exclusiveSuggestions; } } else { // Either the category is not exclusive, or the exclusiveness expired so we should // treat it as a normal category. readSuggestions(category, suggestions, isSmartSuggestionEnabled); } } dedupeSuggestions(suggestions); return suggestions; } Loading Loading @@ -190,6 +201,22 @@ public class SuggestionParser { } } /** * Filter suggestions list so they are all unique. */ private void dedupeSuggestions(List<Tile> suggestions) { final Set<String> intents = new ArraySet<>(); for (int i = suggestions.size() - 1; i >= 0; i--) { final Tile suggestion = suggestions.get(i); final String intentUri = suggestion.intent.toUri(Intent.URI_INTENT_SCHEME); if (intents.contains(intentUri)) { suggestions.remove(i); } else { intents.add(intentUri); } } } @VisibleForTesting void readSuggestions( SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) { Loading Loading @@ -326,6 +353,25 @@ public class SuggestionParser { Settings.Secure.putInt(mContext.getContentResolver(), name, 1); } /** * Whether or not the category's exclusiveness has expired. */ private boolean isExclusiveCategoryExpired(SuggestionCategory category) { final String keySetupTime = category.category + SETUP_TIME; final long currentTime = System.currentTimeMillis(); if (!mSharedPrefs.contains(keySetupTime)) { mSharedPrefs.edit() .putLong(keySetupTime, currentTime) .commit(); } if (category.exclusiveExpireDaysInMillis < 0) { // negative means never expires return false; } final long setupTime = mSharedPrefs.getLong(keySetupTime, 0); return currentTime - setupTime > category.exclusiveExpireDaysInMillis; } private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) { String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled); if (dismissControl == null) { Loading Loading @@ -384,6 +430,7 @@ public class SuggestionParser { public String pkg; public boolean multiple; public boolean exclusive; public long exclusiveExpireDaysInMillis; } private static class SuggestionOrderInflater { Loading @@ -394,6 +441,7 @@ public class SuggestionParser { private static final String ATTR_PACKAGE = "package"; private static final String ATTR_MULTIPLE = "multiple"; private static final String ATTR_EXCLUSIVE = "exclusive"; private static final String ATTR_EXCLUSIVE_EXPIRE_DAYS = "exclusiveExpireDays"; private final Context mContext; Loading Loading @@ -471,6 +519,12 @@ public class SuggestionParser { String exclusive = attrs.getAttributeValue(null, ATTR_EXCLUSIVE); category.exclusive = !TextUtils.isEmpty(exclusive) && Boolean.parseBoolean(exclusive); String expireDaysAttr = attrs.getAttributeValue(null, ATTR_EXCLUSIVE_EXPIRE_DAYS); long expireDays = !TextUtils.isEmpty(expireDaysAttr) ? Integer.parseInt(expireDaysAttr) : -1; category.exclusiveExpireDaysInMillis = DateUtils.DAY_IN_MILLIS * expireDays; return category; } else { throw new IllegalArgumentException("Unknown item " + name); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java +54 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settingslib; import static com.google.common.truth.Truth.assertThat; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading @@ -36,19 +34,24 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.res.ResourceLoader; import org.robolectric.res.builder.DefaultPackageManager; import org.robolectric.res.builder.RobolectricPackageManager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static com.google.common.truth.Truth.assertThat; @RunWith(SettingLibRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SuggestionParserTest { private Context mContext; private RobolectricPackageManager mPackageManager; private SuggestionParser mSuggestionParser; private SuggestionParser.SuggestionCategory mMultipleCategory; private SuggestionParser.SuggestionCategory mExclusiveCategory; private SuggestionParser.SuggestionCategory mExpiredExclusiveCategory; private List<Tile> mSuggestionsBeforeDismiss; private List<Tile> mSuggestionsAfterDismiss; private SharedPreferences mPrefs; Loading @@ -59,6 +62,7 @@ public class SuggestionParserTest { RuntimeEnvironment.setRobolectricPackageManager( new TestPackageManager(RuntimeEnvironment.getAppResourceLoader())); mContext = RuntimeEnvironment.application; mPackageManager = RuntimeEnvironment.getRobolectricPackageManager(); mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); mSuggestion = new Tile(); mSuggestion.intent = new Intent("action"); Loading @@ -70,21 +74,36 @@ public class SuggestionParserTest { mExclusiveCategory = new SuggestionParser.SuggestionCategory(); mExclusiveCategory.category = "category2"; mExclusiveCategory.exclusive = true; mSuggestionParser = new SuggestionParser( mContext, mPrefs, Arrays.asList(mMultipleCategory, mExclusiveCategory), "0,0"); mExpiredExclusiveCategory = new SuggestionParser.SuggestionCategory(); mExpiredExclusiveCategory.category = "category3"; mExpiredExclusiveCategory.exclusive = true; mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0; mSuggestionParser = new SuggestionParser(mContext, mPrefs, Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory), "0,0"); ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1"); info1.activityInfo.packageName = "pkg"; ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, "category1"); infoDupe1.activityInfo.packageName = "pkg"; ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1"); info2.activityInfo.packageName = "pkg2"; ResolveInfo info3 = TileUtilsTest.newInfo(true, "category2"); info3.activityInfo.packageName = "pkg3"; ResolveInfo info4 = TileUtilsTest.newInfo(true, "category3"); info4.activityInfo.packageName = "pkg4"; 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); Intent intent3 = new Intent(Intent.ACTION_MAIN).addCategory("category3"); mPackageManager.addResolveInfoForIntent(intent1, info1); mPackageManager.addResolveInfoForIntent(intent1, info2); mPackageManager.addResolveInfoForIntent(intent1, infoDupe1); mPackageManager.addResolveInfoForIntent(intent2, info3); mPackageManager.addResolveInfoForIntent(intent3, info4); } @Test Loading Loading @@ -115,16 +134,42 @@ public class SuggestionParserTest { } @Test public void testGetSuggestion_exclusiveNotAvailable() { RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent( public void testGetSuggestion_exclusiveNotAvailable_onlyRegularCategoryAndNoDupe() { mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category2"), "pkg3"); mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category3"), "pkg4"); // If exclusive item is not available, the other categories should be shown final List<Tile> suggestions = mSuggestionParser.getSuggestions(); assertThat(suggestions).hasSize(2); assertThat(suggestions.get(0).category).isEqualTo("category1"); assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg"); assertThat(suggestions.get(1).category).isEqualTo("category1"); assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2"); } @Test public void testGetSuggestion_exclusiveExpiredAvailable_shouldLoadWithRegularCategory() { // First remove permanent exclusive mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category2"), "pkg3"); // Set the other exclusive to be expired. mPrefs.edit() .putLong(mExpiredExclusiveCategory.category + "_setup_time", System.currentTimeMillis() - 1000) .commit(); // If exclusive is expired, they should be shown together with the other categories final List<Tile> suggestions = mSuggestionParser.getSuggestions(); assertThat(suggestions).hasSize(3); assertThat(suggestions.get(0).category).isEqualTo("category1"); assertThat(suggestions.get(1).category).isEqualTo("category1"); assertThat(suggestions.get(2).category).isEqualTo("category3"); } @Test Loading Loading
packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java +63 −9 Original line number Diff line number Diff line Loading @@ -32,20 +32,25 @@ import android.os.UserManager; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; import android.util.Xml; import android.view.InflateException; import com.android.settingslib.drawer.Tile; import com.android.settingslib.drawer.TileUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; public class SuggestionParser { Loading Loading @@ -104,8 +109,8 @@ public class SuggestionParser { private final String mSmartDismissControl; public SuggestionParser( Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) { public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) { this( context, sharedPrefs, Loading Loading @@ -138,19 +143,25 @@ public class SuggestionParser { final int N = mSuggestionList.size(); for (int i = 0; i < N; i++) { final SuggestionCategory category = mSuggestionList.get(i); if (category.exclusive) { if (category.exclusive && !isExclusiveCategoryExpired(category)) { // 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<Tile> exclusiveSuggestions = new ArrayList<>(); readSuggestions(category, exclusiveSuggestions, isSmartSuggestionEnabled); final List<Tile> exclusiveSuggestions = new ArrayList<>(); // Read suggestion and force isSmartSuggestion to be false so the rule defined // from each suggestion itself is used. readSuggestions(category, exclusiveSuggestions, false /* isSmartSuggestion */); if (!exclusiveSuggestions.isEmpty()) { return exclusiveSuggestions; } } else { // Either the category is not exclusive, or the exclusiveness expired so we should // treat it as a normal category. readSuggestions(category, suggestions, isSmartSuggestionEnabled); } } dedupeSuggestions(suggestions); return suggestions; } Loading Loading @@ -190,6 +201,22 @@ public class SuggestionParser { } } /** * Filter suggestions list so they are all unique. */ private void dedupeSuggestions(List<Tile> suggestions) { final Set<String> intents = new ArraySet<>(); for (int i = suggestions.size() - 1; i >= 0; i--) { final Tile suggestion = suggestions.get(i); final String intentUri = suggestion.intent.toUri(Intent.URI_INTENT_SCHEME); if (intents.contains(intentUri)) { suggestions.remove(i); } else { intents.add(intentUri); } } } @VisibleForTesting void readSuggestions( SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) { Loading Loading @@ -326,6 +353,25 @@ public class SuggestionParser { Settings.Secure.putInt(mContext.getContentResolver(), name, 1); } /** * Whether or not the category's exclusiveness has expired. */ private boolean isExclusiveCategoryExpired(SuggestionCategory category) { final String keySetupTime = category.category + SETUP_TIME; final long currentTime = System.currentTimeMillis(); if (!mSharedPrefs.contains(keySetupTime)) { mSharedPrefs.edit() .putLong(keySetupTime, currentTime) .commit(); } if (category.exclusiveExpireDaysInMillis < 0) { // negative means never expires return false; } final long setupTime = mSharedPrefs.getLong(keySetupTime, 0); return currentTime - setupTime > category.exclusiveExpireDaysInMillis; } private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) { String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled); if (dismissControl == null) { Loading Loading @@ -384,6 +430,7 @@ public class SuggestionParser { public String pkg; public boolean multiple; public boolean exclusive; public long exclusiveExpireDaysInMillis; } private static class SuggestionOrderInflater { Loading @@ -394,6 +441,7 @@ public class SuggestionParser { private static final String ATTR_PACKAGE = "package"; private static final String ATTR_MULTIPLE = "multiple"; private static final String ATTR_EXCLUSIVE = "exclusive"; private static final String ATTR_EXCLUSIVE_EXPIRE_DAYS = "exclusiveExpireDays"; private final Context mContext; Loading Loading @@ -471,6 +519,12 @@ public class SuggestionParser { String exclusive = attrs.getAttributeValue(null, ATTR_EXCLUSIVE); category.exclusive = !TextUtils.isEmpty(exclusive) && Boolean.parseBoolean(exclusive); String expireDaysAttr = attrs.getAttributeValue(null, ATTR_EXCLUSIVE_EXPIRE_DAYS); long expireDays = !TextUtils.isEmpty(expireDaysAttr) ? Integer.parseInt(expireDaysAttr) : -1; category.exclusiveExpireDaysInMillis = DateUtils.DAY_IN_MILLIS * expireDays; return category; } else { throw new IllegalArgumentException("Unknown item " + name); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java +54 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settingslib; import static com.google.common.truth.Truth.assertThat; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading @@ -36,19 +34,24 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.res.ResourceLoader; import org.robolectric.res.builder.DefaultPackageManager; import org.robolectric.res.builder.RobolectricPackageManager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static com.google.common.truth.Truth.assertThat; @RunWith(SettingLibRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SuggestionParserTest { private Context mContext; private RobolectricPackageManager mPackageManager; private SuggestionParser mSuggestionParser; private SuggestionParser.SuggestionCategory mMultipleCategory; private SuggestionParser.SuggestionCategory mExclusiveCategory; private SuggestionParser.SuggestionCategory mExpiredExclusiveCategory; private List<Tile> mSuggestionsBeforeDismiss; private List<Tile> mSuggestionsAfterDismiss; private SharedPreferences mPrefs; Loading @@ -59,6 +62,7 @@ public class SuggestionParserTest { RuntimeEnvironment.setRobolectricPackageManager( new TestPackageManager(RuntimeEnvironment.getAppResourceLoader())); mContext = RuntimeEnvironment.application; mPackageManager = RuntimeEnvironment.getRobolectricPackageManager(); mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); mSuggestion = new Tile(); mSuggestion.intent = new Intent("action"); Loading @@ -70,21 +74,36 @@ public class SuggestionParserTest { mExclusiveCategory = new SuggestionParser.SuggestionCategory(); mExclusiveCategory.category = "category2"; mExclusiveCategory.exclusive = true; mSuggestionParser = new SuggestionParser( mContext, mPrefs, Arrays.asList(mMultipleCategory, mExclusiveCategory), "0,0"); mExpiredExclusiveCategory = new SuggestionParser.SuggestionCategory(); mExpiredExclusiveCategory.category = "category3"; mExpiredExclusiveCategory.exclusive = true; mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0; mSuggestionParser = new SuggestionParser(mContext, mPrefs, Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory), "0,0"); ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1"); info1.activityInfo.packageName = "pkg"; ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, "category1"); infoDupe1.activityInfo.packageName = "pkg"; ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1"); info2.activityInfo.packageName = "pkg2"; ResolveInfo info3 = TileUtilsTest.newInfo(true, "category2"); info3.activityInfo.packageName = "pkg3"; ResolveInfo info4 = TileUtilsTest.newInfo(true, "category3"); info4.activityInfo.packageName = "pkg4"; 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); Intent intent3 = new Intent(Intent.ACTION_MAIN).addCategory("category3"); mPackageManager.addResolveInfoForIntent(intent1, info1); mPackageManager.addResolveInfoForIntent(intent1, info2); mPackageManager.addResolveInfoForIntent(intent1, infoDupe1); mPackageManager.addResolveInfoForIntent(intent2, info3); mPackageManager.addResolveInfoForIntent(intent3, info4); } @Test Loading Loading @@ -115,16 +134,42 @@ public class SuggestionParserTest { } @Test public void testGetSuggestion_exclusiveNotAvailable() { RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent( public void testGetSuggestion_exclusiveNotAvailable_onlyRegularCategoryAndNoDupe() { mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category2"), "pkg3"); mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category3"), "pkg4"); // If exclusive item is not available, the other categories should be shown final List<Tile> suggestions = mSuggestionParser.getSuggestions(); assertThat(suggestions).hasSize(2); assertThat(suggestions.get(0).category).isEqualTo("category1"); assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg"); assertThat(suggestions.get(1).category).isEqualTo("category1"); assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2"); } @Test public void testGetSuggestion_exclusiveExpiredAvailable_shouldLoadWithRegularCategory() { // First remove permanent exclusive mPackageManager.removeResolveInfosForIntent( new Intent(Intent.ACTION_MAIN).addCategory("category2"), "pkg3"); // Set the other exclusive to be expired. mPrefs.edit() .putLong(mExpiredExclusiveCategory.category + "_setup_time", System.currentTimeMillis() - 1000) .commit(); // If exclusive is expired, they should be shown together with the other categories final List<Tile> suggestions = mSuggestionParser.getSuggestions(); assertThat(suggestions).hasSize(3); assertThat(suggestions.get(0).category).isEqualTo("category1"); assertThat(suggestions.get(1).category).isEqualTo("category1"); assertThat(suggestions.get(2).category).isEqualTo("category3"); } @Test Loading