1 package com.android.settings.search; 2 3 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SEARCHABLE; 4 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; 5 6 import static com.google.common.truth.Truth.assertThat; 7 8 import static org.mockito.Mockito.mock; 9 import static org.mockito.Mockito.spy; 10 import static org.mockito.Mockito.when; 11 12 import android.Manifest; 13 import android.content.Context; 14 import android.content.pm.ActivityInfo; 15 import android.content.pm.ProviderInfo; 16 import android.database.Cursor; 17 import android.net.Uri; 18 import android.os.Bundle; 19 import android.provider.SearchIndexablesContract; 20 21 import com.android.settings.R; 22 import com.android.settings.accounts.ManagedProfileSettings; 23 import com.android.settings.dashboard.CategoryManager; 24 import com.android.settings.homepage.TopLevelSettings; 25 import com.android.settings.network.NetworkDashboardFragment; 26 import com.android.settings.testutils.FakeFeatureFactory; 27 import com.android.settingslib.drawer.ActivityTile; 28 import com.android.settingslib.drawer.CategoryKey; 29 import com.android.settingslib.drawer.DashboardCategory; 30 import com.android.settingslib.search.SearchIndexableData; 31 32 import org.junit.After; 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.robolectric.RobolectricTestRunner; 37 import org.robolectric.RuntimeEnvironment; 38 import org.robolectric.annotation.Config; 39 import org.robolectric.annotation.Implementation; 40 import org.robolectric.annotation.Implements; 41 import org.robolectric.annotation.Resetter; 42 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.List; 46 47 @RunWith(RobolectricTestRunner.class) 48 @Config(shadows = SettingsSearchIndexablesProviderTest.ShadowCategoryManager.class) 49 public class SettingsSearchIndexablesProviderTest { 50 51 private static final String PACKAGE_NAME = "com.android.settings"; 52 private static final String BASE_AUTHORITY = "content://" + PACKAGE_NAME + "/"; 53 54 private Context mContext; 55 private SettingsSearchIndexablesProvider mProvider; 56 private FakeFeatureFactory mFakeFeatureFactory; 57 58 @Before setUp()59 public void setUp() { 60 mContext = RuntimeEnvironment.application; 61 mProvider = spy(new SettingsSearchIndexablesProvider()); 62 ProviderInfo info = new ProviderInfo(); 63 info.exported = true; 64 info.grantUriPermissions = true; 65 info.authority = PACKAGE_NAME; 66 info.readPermission = Manifest.permission.READ_SEARCH_INDEXABLES; 67 mProvider.attachInfo(RuntimeEnvironment.application, info); 68 69 final SearchFeatureProvider featureProvider = new SearchFeatureProviderImpl(); 70 featureProvider.getSearchIndexableResources().getProviderValues().clear(); 71 featureProvider.getSearchIndexableResources().getProviderValues() 72 .add(new SearchIndexableData(FakeSettingsFragment.class, 73 FakeSettingsFragment.SEARCH_INDEX_DATA_PROVIDER)); 74 mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); 75 mFakeFeatureFactory.searchFeatureProvider = featureProvider; 76 77 final ActivityInfo activityInfo = new ActivityInfo(); 78 activityInfo.packageName = "pkg"; 79 activityInfo.name = "class"; 80 activityInfo.metaData = new Bundle(); 81 activityInfo.metaData.putString(META_DATA_PREFERENCE_TITLE, "title"); 82 final DashboardCategory category = new DashboardCategory("key"); 83 when(mFakeFeatureFactory.dashboardFeatureProvider.getAllCategories()) 84 .thenReturn(Arrays.asList(category)); 85 category.addTile(new ActivityTile(activityInfo, category.key)); 86 ShadowCategoryManager.setDashboardCategory(category); 87 } 88 89 @After cleanUp()90 public void cleanUp() { 91 ShadowCategoryManager.reset(); 92 mFakeFeatureFactory.searchFeatureProvider = mock(SearchFeatureProvider.class); 93 } 94 95 @Test testRawColumnFetched()96 public void testRawColumnFetched() { 97 Uri rawUri = Uri.parse(BASE_AUTHORITY + SearchIndexablesContract.INDEXABLES_RAW_PATH); 98 99 final Cursor cursor = mProvider.query(rawUri, 100 SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, null, null, null); 101 102 cursor.moveToFirst(); 103 assertThat(cursor.getString(1)).isEqualTo(FakeSettingsFragment.TITLE); 104 assertThat(cursor.getString(2)).isEqualTo(FakeSettingsFragment.SUMMARY_ON); 105 assertThat(cursor.getString(3)).isEqualTo(FakeSettingsFragment.SUMMARY_OFF); 106 assertThat(cursor.getString(4)).isEqualTo(FakeSettingsFragment.ENTRIES); 107 assertThat(cursor.getString(5)).isEqualTo(FakeSettingsFragment.KEYWORDS); 108 assertThat(cursor.getString(6)).isEqualTo(FakeSettingsFragment.SCREEN_TITLE); 109 assertThat(cursor.getString(7)).isEqualTo(FakeSettingsFragment.CLASS_NAME); 110 assertThat(cursor.getInt(8)).isEqualTo(FakeSettingsFragment.ICON); 111 assertThat(cursor.getString(9)).isEqualTo(FakeSettingsFragment.INTENT_ACTION); 112 assertThat(cursor.getString(10)).isEqualTo(FakeSettingsFragment.TARGET_PACKAGE); 113 assertThat(cursor.getString(11)).isEqualTo(FakeSettingsFragment.TARGET_CLASS); 114 assertThat(cursor.getString(12)).isEqualTo(FakeSettingsFragment.KEY); 115 } 116 117 @Test testResourcesColumnFetched()118 public void testResourcesColumnFetched() { 119 Uri rawUri = Uri.parse(BASE_AUTHORITY + SearchIndexablesContract.INDEXABLES_XML_RES_PATH); 120 121 final Cursor cursor = mProvider.query(rawUri, 122 SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, null, null, null); 123 124 cursor.moveToFirst(); 125 assertThat(cursor.getCount()).isEqualTo(1); 126 assertThat(cursor.getInt(1)).isEqualTo(R.xml.display_settings); 127 assertThat(cursor.getString(2)).isEqualTo(FakeSettingsFragment.CLASS_NAME); 128 assertThat(cursor.getInt(3)).isEqualTo(0); 129 assertThat(cursor.getString(4)).isNull(); 130 assertThat(cursor.getString(5)).isNull(); 131 assertThat(cursor.getString(6)).isNull(); 132 } 133 134 @Test 135 @Config(qualifiers = "mcc999") testNonIndexablesColumnFetched()136 public void testNonIndexablesColumnFetched() { 137 final Uri rawUri = Uri.parse( 138 BASE_AUTHORITY + SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH); 139 140 final List<String> keys = new ArrayList<>(); 141 142 try (Cursor cursor = mProvider.query(rawUri, 143 SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS, null, null, null)) { 144 while (cursor.moveToNext()) { 145 keys.add(cursor.getString(0)); 146 } 147 } 148 149 assertThat(keys).hasSize(3); 150 assertThat(keys).containsAtLeast("pref_key_1", "pref_key_3", "pref_key_5"); 151 } 152 153 @Test refreshSearchEnabledState_classNotFoundInCategoryMap_hasInjectionRawData()154 public void refreshSearchEnabledState_classNotFoundInCategoryMap_hasInjectionRawData() { 155 mProvider.refreshSearchEnabledState(mContext, 156 ManagedProfileSettings.SEARCH_INDEX_DATA_PROVIDER); 157 158 assertThat(mProvider.getInjectionIndexableRawData(mContext)).isNotEmpty(); 159 } 160 161 @Test refreshSearchEnabledState_noDashboardCategory_hasInjectionRawData()162 public void refreshSearchEnabledState_noDashboardCategory_hasInjectionRawData() { 163 ShadowCategoryManager.setDashboardCategory(null); 164 165 mProvider.refreshSearchEnabledState(mContext, 166 TopLevelSettings.SEARCH_INDEX_DATA_PROVIDER); 167 168 assertThat(mProvider.getInjectionIndexableRawData(mContext)).isNotEmpty(); 169 } 170 171 @Test refreshSearchEnabledState_pageSearchEnabled_hasInjectionRawData()172 public void refreshSearchEnabledState_pageSearchEnabled_hasInjectionRawData() { 173 mProvider.refreshSearchEnabledState(mContext, 174 NetworkDashboardFragment.SEARCH_INDEX_DATA_PROVIDER); 175 176 assertThat(mProvider.getInjectionIndexableRawData(mContext)).isNotEmpty(); 177 } 178 179 @Test refreshSearchEnabledState_pageSearchDisable_noInjectionRawData()180 public void refreshSearchEnabledState_pageSearchDisable_noInjectionRawData() { 181 mProvider.refreshSearchEnabledState(mContext, 182 TopLevelSettings.SEARCH_INDEX_DATA_PROVIDER); 183 184 assertThat(mProvider.getInjectionIndexableRawData(mContext)).isEmpty(); 185 } 186 187 @Test isEligibleForIndexing_isSettingsInjectedItem_shouldReturnFalse()188 public void isEligibleForIndexing_isSettingsInjectedItem_shouldReturnFalse() { 189 final ActivityInfo activityInfo = new ActivityInfo(); 190 activityInfo.packageName = PACKAGE_NAME; 191 activityInfo.name = "class"; 192 final ActivityTile activityTile = new ActivityTile(activityInfo, 193 CategoryKey.CATEGORY_SYSTEM); 194 195 assertThat(mProvider.isEligibleForIndexing(PACKAGE_NAME, activityTile)).isFalse(); 196 } 197 198 @Test isEligibleForIndexing_normalInjectedItem_shouldReturnTrue()199 public void isEligibleForIndexing_normalInjectedItem_shouldReturnTrue() { 200 final ActivityInfo activityInfo = new ActivityInfo(); 201 activityInfo.packageName = "pkg"; 202 activityInfo.name = "class"; 203 final ActivityTile activityTile = new ActivityTile(activityInfo, 204 CategoryKey.CATEGORY_CONNECT); 205 206 assertThat(mProvider.isEligibleForIndexing(PACKAGE_NAME, activityTile)).isTrue(); 207 } 208 209 @Test isEligibleForIndexing_disabledByMetadata_shouldReturnFalse()210 public void isEligibleForIndexing_disabledByMetadata_shouldReturnFalse() { 211 final ActivityInfo activityInfo = new ActivityInfo(); 212 activityInfo.packageName = PACKAGE_NAME; 213 activityInfo.name = "class"; 214 activityInfo.metaData = new Bundle(); 215 activityInfo.metaData.putBoolean(META_DATA_PREFERENCE_SEARCHABLE, false); 216 final ActivityTile activityTile = new ActivityTile(activityInfo, 217 CategoryKey.CATEGORY_CONNECT); 218 219 assertThat(mProvider.isEligibleForIndexing(PACKAGE_NAME, activityTile)).isFalse(); 220 } 221 222 @Implements(CategoryManager.class) 223 public static class ShadowCategoryManager { 224 225 private static DashboardCategory sCategory; 226 227 @Resetter reset()228 static void reset() { 229 sCategory = null; 230 } 231 232 @Implementation getTilesByCategory(Context context, String categoryKey)233 public DashboardCategory getTilesByCategory(Context context, String categoryKey) { 234 return sCategory; 235 } 236 setDashboardCategory(DashboardCategory category)237 static void setDashboardCategory(DashboardCategory category) { 238 sCategory = category; 239 } 240 } 241 } 242