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