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