Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 17 | package com.android.settingslib.suggestions; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 18 | |
Fan Zhang | 7b77cf8 | 2017-07-21 10:21:36 -0700 | [diff] [blame] | 19 | import static com.google.common.truth.Truth.assertThat; |
| 20 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 21 | import android.content.ComponentName; |
Fan Zhang | 73b161d | 2017-02-08 11:46:54 -0800 | [diff] [blame] | 22 | import android.content.Context; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 23 | import android.content.Intent; |
| 24 | import android.content.SharedPreferences; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 25 | import android.content.pm.ResolveInfo; |
Fan Zhang | 73b161d | 2017-02-08 11:46:54 -0800 | [diff] [blame] | 26 | import android.os.Bundle; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 27 | import android.preference.PreferenceManager; |
| 28 | |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 29 | import com.android.settingslib.SettingLibRobolectricTestRunner; |
| 30 | import com.android.settingslib.TestConfig; |
Fan Zhang | 73b161d | 2017-02-08 11:46:54 -0800 | [diff] [blame] | 31 | import com.android.settingslib.drawer.Tile; |
| 32 | import com.android.settingslib.drawer.TileUtilsTest; |
| 33 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 34 | import org.junit.Before; |
| 35 | import org.junit.Test; |
| 36 | import org.junit.runner.RunWith; |
Fan Zhang | 73b161d | 2017-02-08 11:46:54 -0800 | [diff] [blame] | 37 | import org.robolectric.RuntimeEnvironment; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 38 | import org.robolectric.annotation.Config; |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 39 | import org.robolectric.res.ResourceLoader; |
| 40 | import org.robolectric.res.builder.DefaultPackageManager; |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 41 | import org.robolectric.res.builder.RobolectricPackageManager; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 42 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 43 | import java.util.ArrayList; |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 44 | import java.util.Arrays; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 45 | import java.util.List; |
| 46 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 47 | @RunWith(SettingLibRobolectricTestRunner.class) |
| 48 | @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) |
| 49 | public class SuggestionParserTest { |
| 50 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 51 | private Context mContext; |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 52 | private RobolectricPackageManager mPackageManager; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 53 | private SuggestionParser mSuggestionParser; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 54 | private SuggestionCategory mMultipleCategory; |
| 55 | private SuggestionCategory mExclusiveCategory; |
| 56 | private SuggestionCategory mExpiredExclusiveCategory; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 57 | private List<Tile> mSuggestionsBeforeDismiss; |
| 58 | private List<Tile> mSuggestionsAfterDismiss; |
| 59 | private SharedPreferences mPrefs; |
| 60 | private Tile mSuggestion; |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 61 | |
| 62 | @Before |
| 63 | public void setUp() { |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 64 | RuntimeEnvironment.setRobolectricPackageManager( |
| 65 | new TestPackageManager(RuntimeEnvironment.getAppResourceLoader())); |
| 66 | mContext = RuntimeEnvironment.application; |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 67 | mPackageManager = RuntimeEnvironment.getRobolectricPackageManager(); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 68 | mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); |
| 69 | mSuggestion = new Tile(); |
| 70 | mSuggestion.intent = new Intent("action"); |
| 71 | mSuggestion.intent.setComponent(new ComponentName("pkg", "cls")); |
| 72 | mSuggestion.metaData = new Bundle(); |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 73 | mMultipleCategory = new SuggestionCategory(); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 74 | mMultipleCategory.category = "category1"; |
| 75 | mMultipleCategory.multiple = true; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 76 | mExclusiveCategory = new SuggestionCategory(); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 77 | mExclusiveCategory.category = "category2"; |
| 78 | mExclusiveCategory.exclusive = true; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 79 | mExpiredExclusiveCategory = new SuggestionCategory(); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 80 | mExpiredExclusiveCategory.category = "category3"; |
| 81 | mExpiredExclusiveCategory.exclusive = true; |
| 82 | mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0; |
| 83 | |
| 84 | mSuggestionParser = new SuggestionParser(mContext, mPrefs, |
| 85 | Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory), |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 86 | "0"); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 87 | |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 88 | ResolveInfo info1 = TileUtilsTest.newInfo(true, null); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 89 | info1.activityInfo.packageName = "pkg"; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 90 | ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, null); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 91 | infoDupe1.activityInfo.packageName = "pkg"; |
| 92 | |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 93 | ResolveInfo info2 = TileUtilsTest.newInfo(true, null); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 94 | info2.activityInfo.packageName = "pkg2"; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 95 | ResolveInfo info3 = TileUtilsTest.newInfo(true, null); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 96 | info3.activityInfo.packageName = "pkg3"; |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 97 | ResolveInfo info4 = TileUtilsTest.newInfo(true, null); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 98 | info4.activityInfo.packageName = "pkg4"; |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 99 | |
| 100 | Intent intent1 = new Intent(Intent.ACTION_MAIN).addCategory("category1"); |
| 101 | Intent intent2 = new Intent(Intent.ACTION_MAIN).addCategory("category2"); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 102 | Intent intent3 = new Intent(Intent.ACTION_MAIN).addCategory("category3"); |
| 103 | |
| 104 | mPackageManager.addResolveInfoForIntent(intent1, info1); |
| 105 | mPackageManager.addResolveInfoForIntent(intent1, info2); |
| 106 | mPackageManager.addResolveInfoForIntent(intent1, infoDupe1); |
| 107 | mPackageManager.addResolveInfoForIntent(intent2, info3); |
| 108 | mPackageManager.addResolveInfoForIntent(intent3, info4); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | @Test |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 112 | public void dismissSuggestion_shouldDismiss() { |
| 113 | assertThat(mSuggestionParser.dismissSuggestion(mSuggestion)).isTrue(); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | @Test |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 117 | public void testGetSuggestions_withoutSmartSuggestions_shouldDismiss() { |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 118 | readAndDismissSuggestion(false); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 119 | mSuggestionParser.readSuggestions(mMultipleCategory, mSuggestionsAfterDismiss, false); |
| 120 | assertThat(mSuggestionsBeforeDismiss).hasSize(2); |
| 121 | assertThat(mSuggestionsAfterDismiss).hasSize(1); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 122 | assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0)); |
| 123 | } |
| 124 | |
| 125 | @Test |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 126 | public void testGetSuggestions_withSmartSuggestions_shouldDismiss() { |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 127 | readAndDismissSuggestion(true); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 128 | assertThat(mSuggestionsBeforeDismiss).hasSize(2); |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 129 | assertThat(mSuggestionsAfterDismiss).hasSize(1); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 130 | } |
| 131 | |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 132 | @Test |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 133 | public void testGetSuggestion_exclusiveNotAvailable_onlyRegularCategoryAndNoDupe() { |
| 134 | mPackageManager.removeResolveInfosForIntent( |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 135 | new Intent(Intent.ACTION_MAIN).addCategory("category2"), |
| 136 | "pkg3"); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 137 | mPackageManager.removeResolveInfosForIntent( |
| 138 | new Intent(Intent.ACTION_MAIN).addCategory("category3"), |
| 139 | "pkg4"); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 140 | |
| 141 | // If exclusive item is not available, the other categories should be shown |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 142 | final SuggestionList sl = |
| 143 | mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */); |
| 144 | final List<Tile> suggestions = sl.getSuggestions(); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 145 | assertThat(suggestions).hasSize(2); |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 146 | |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 147 | assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg"); |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 148 | assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2"); |
| 149 | } |
| 150 | |
| 151 | @Test |
| 152 | public void testGetSuggestion_exclusiveExpiredAvailable_shouldLoadWithRegularCategory() { |
| 153 | // First remove permanent exclusive |
| 154 | mPackageManager.removeResolveInfosForIntent( |
| 155 | new Intent(Intent.ACTION_MAIN).addCategory("category2"), |
| 156 | "pkg3"); |
| 157 | // Set the other exclusive to be expired. |
| 158 | mPrefs.edit() |
| 159 | .putLong(mExpiredExclusiveCategory.category + "_setup_time", |
| 160 | System.currentTimeMillis() - 1000) |
| 161 | .commit(); |
| 162 | |
| 163 | // If exclusive is expired, they should be shown together with the other categories |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 164 | final SuggestionList sl = |
| 165 | mSuggestionParser.getSuggestions(true /* isSmartSuggestionEnabled */); |
| 166 | final List<Tile> suggestions = sl.getSuggestions(); |
| 167 | |
Fan Zhang | a0f8d23 | 2017-05-08 09:33:04 -0700 | [diff] [blame] | 168 | assertThat(suggestions).hasSize(3); |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 169 | |
| 170 | final List<Tile> category1Suggestions = sl.getSuggestionForCategory("category1"); |
| 171 | final List<Tile> category3Suggestions = sl.getSuggestionForCategory("category3"); |
| 172 | |
| 173 | assertThat(category1Suggestions).hasSize(2); |
| 174 | assertThat(category3Suggestions).hasSize(1); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | @Test |
| 178 | public void testGetSuggestions_exclusive() { |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 179 | final SuggestionList sl = |
| 180 | mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */); |
| 181 | final List<Tile> suggestions = sl.getSuggestions(); |
| 182 | |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 183 | assertThat(suggestions).hasSize(1); |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 184 | assertThat(sl.getSuggestionForCategory("category2")).hasSize(1); |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 185 | } |
| 186 | |
Fan Zhang | 7b77cf8 | 2017-07-21 10:21:36 -0700 | [diff] [blame] | 187 | @Test |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 188 | public void isSuggestionDismissed_dismissedSuggestion_shouldReturnTrue() { |
Fan Zhang | 7b77cf8 | 2017-07-21 10:21:36 -0700 | [diff] [blame] | 189 | final Tile suggestion = new Tile(); |
| 190 | suggestion.metaData = new Bundle(); |
| 191 | suggestion.metaData.putString(SuggestionParser.META_DATA_DISMISS_CONTROL, "1,2,3"); |
| 192 | suggestion.intent = new Intent().setComponent(new ComponentName("pkg", "cls")); |
| 193 | |
| 194 | // Dismiss suggestion when smart suggestion is not enabled. |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 195 | mSuggestionParser.dismissSuggestion(suggestion); |
Fan Zhang | 7b77cf8 | 2017-07-21 10:21:36 -0700 | [diff] [blame] | 196 | |
Fan Zhang | 7b77cf8 | 2017-07-21 10:21:36 -0700 | [diff] [blame] | 197 | assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */)) |
| 198 | .isTrue(); |
| 199 | } |
| 200 | |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 201 | private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) { |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 202 | mSuggestionsBeforeDismiss = new ArrayList<>(); |
| 203 | mSuggestionsAfterDismiss = new ArrayList<>(); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 204 | mSuggestionParser.readSuggestions( |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 205 | mMultipleCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled); |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 206 | |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 207 | final Tile suggestion = mSuggestionsBeforeDismiss.get(0); |
Fan Zhang | c07ae9c | 2017-08-03 17:33:18 -0700 | [diff] [blame] | 208 | if (mSuggestionParser.dismissSuggestion(suggestion)) { |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 209 | RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent( |
Fan Zhang | e138ef1 | 2017-05-11 15:29:56 -0700 | [diff] [blame] | 210 | new Intent(Intent.ACTION_MAIN).addCategory(mMultipleCategory.category), |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 211 | suggestion.intent.getComponent().getPackageName()); |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 212 | } |
| 213 | mSuggestionParser.readSuggestions( |
Maurice Lam | f74b9e5 | 2017-03-23 14:58:47 -0700 | [diff] [blame] | 214 | mMultipleCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled); |
| 215 | } |
| 216 | |
| 217 | private static class TestPackageManager extends DefaultPackageManager { |
| 218 | |
| 219 | TestPackageManager(ResourceLoader appResourceLoader) { |
| 220 | super(appResourceLoader); |
| 221 | } |
| 222 | |
| 223 | @Override |
| 224 | public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { |
| 225 | return super.queryIntentActivities(intent, flags); |
| 226 | } |
Soroosh Mariooryad | 56ce766 | 2017-02-06 15:23:00 -0800 | [diff] [blame] | 227 | } |
| 228 | } |