• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
17 
18 package com.android.settings.search2;
19 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.ContentProvider;
23 import android.content.ContentValues;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.PackageManager;
27 import android.content.pm.ProviderInfo;
28 import android.content.pm.ResolveInfo;
29 import android.database.Cursor;
30 import android.database.MatrixCursor;
31 import android.database.sqlite.SQLiteDatabase;
32 import android.net.Uri;
33 import android.os.Build;
34 import android.provider.SearchIndexableResource;
35 import android.util.ArrayMap;
36 import com.android.settings.R;
37 import com.android.settings.SettingsRobolectricTestRunner;
38 import com.android.settings.TestConfig;
39 import com.android.settings.search.IndexDatabaseHelper;
40 import com.android.settings.search.IndexingCallback;
41 import com.android.settings.search.SearchIndexableRaw;
42 import com.android.settings.testutils.DatabaseTestUtils;
43 import com.android.settings.testutils.shadow.ShadowDatabaseIndexingUtils;
44 import com.android.settings.testutils.shadow.ShadowRunnableAsyncTask;
45 import org.junit.After;
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.robolectric.Robolectric;
52 import org.robolectric.RuntimeEnvironment;
53 import org.robolectric.annotation.Config;
54 import org.robolectric.shadows.ShadowContentResolver;
55 
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.HashMap;
59 import java.util.HashSet;
60 import java.util.List;
61 import java.util.Locale;
62 import java.util.Map;
63 import java.util.Set;
64 
65 import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
66 import static com.google.common.truth.Truth.assertThat;
67 import static org.mockito.Matchers.any;
68 import static org.mockito.Matchers.anyInt;
69 import static org.mockito.Matchers.anyList;
70 import static org.mockito.Matchers.anyMap;
71 import static org.mockito.Matchers.anyString;
72 import static org.mockito.Mockito.doNothing;
73 import static org.mockito.Mockito.doReturn;
74 import static org.mockito.Mockito.mock;
75 import static org.mockito.Mockito.spy;
76 import static org.mockito.Mockito.times;
77 import static org.mockito.Mockito.verify;
78 import static org.mockito.Mockito.when;
79 
80 @RunWith(SettingsRobolectricTestRunner.class)
81 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
82         shadows = {ShadowRunnableAsyncTask.class})
83 public class DatabaseIndexingManagerTest {
84     private final String localeStr = "en_US";
85 
86     private final int rank = 8;
87     private final String title = "title\u2011title";
88     private final String updatedTitle = "title-title";
89     private final String normalizedTitle = "titletitle";
90     private final String summaryOn = "summary\u2011on";
91     private final String updatedSummaryOn = "summary-on";
92     private final String normalizedSummaryOn = "summaryon";
93     private final String summaryOff = "summary\u2011off";
94     private final String updatedSummaryOff = "summary-off";
95     private final String normalizedSummaryOff = "summaryoff";
96     private final String entries = "entries";
97     private final String keywords = "keywords, keywordss, keywordsss";
98     private final String spaceDelimittedKeywords = "keywords keywordss keywordsss";
99     private final String screenTitle = "screen title";
100     private final String className = "class name";
101     private final int iconResId = 0xff;
102     private final int noIcon = 0;
103     private final String action = "action";
104     private final String targetPackage = "target package";
105     private final String targetClass = "target class";
106     private final String packageName = "package name";
107     private final String key = "key";
108     private final int userId = -1;
109     private final boolean enabled = true;
110 
111     private final String AUTHORITY_ONE = "authority";
112     private final String PACKAGE_ONE = "com.android.settings";
113 
114     private final String TITLE_ONE = "title one";
115     private final String TITLE_TWO = "title two";
116     private final String KEY_ONE = "key one";
117     private final String KEY_TWO = "key two";
118 
119     private Context mContext;
120 
121     private DatabaseIndexingManager mManager;
122     private SQLiteDatabase mDb;
123 
124     @Mock
125     private PackageManager mPackageManager;
126 
127     @Before
setUp()128     public void setUp() {
129         MockitoAnnotations.initMocks(this);
130         mContext = spy(RuntimeEnvironment.application);
131         mManager = spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
132         mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
133 
134         doReturn(mPackageManager).when(mContext).getPackageManager();
135     }
136 
137     @After
cleanUp()138     public void cleanUp() {
139         DatabaseTestUtils.clearDb();
140     }
141 
142     @Test
testDatabaseSchema()143     public void testDatabaseSchema() {
144         Cursor dbCursor = mDb.query("prefs_index", null, null, null, null, null, null);
145         List<String> columnNames = new ArrayList<>(Arrays.asList(dbCursor.getColumnNames()));
146         // Note that docid is not included.
147         List<String> expColumnNames = new ArrayList<>(Arrays.asList(new String[]{
148                 "locale",
149                 "data_rank",
150                 "data_title",
151                 "data_title_normalized",
152                 "data_summary_on",
153                 "data_summary_on_normalized",
154                 "data_summary_off",
155                 "data_summary_off_normalized",
156                 "data_entries",
157                 "data_keywords",
158                 "class_name",
159                 "screen_title",
160                 "intent_action",
161                 "intent_target_package",
162                 "intent_target_class",
163                 "icon",
164                 "enabled",
165                 "data_key_reference",
166                 "user_id",
167                 "payload_type",
168                 "payload"
169         }));
170         // Prevent database schema regressions
171         assertThat(columnNames).containsAllIn(expColumnNames);
172     }
173 
174     // Tests for the flow: IndexOneRaw -> UpdateOneRowWithFilteredData -> UpdateOneRow
175 
176     @Test
testInsertRawColumn_rowInserted()177     public void testInsertRawColumn_rowInserted() {
178         SearchIndexableRaw raw = getFakeRaw();
179         mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
180         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
181         assertThat(cursor.getCount()).isEqualTo(1);
182     }
183 
184     @Test
testInsertRawColumn_rowMatches()185     public void testInsertRawColumn_rowMatches() {
186         SearchIndexableRaw raw = getFakeRaw();
187         mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
188         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
189         cursor.moveToPosition(0);
190 
191         // Locale
192         assertThat(cursor.getString(0)).isEqualTo(localeStr);
193         // Data Rank
194         assertThat(cursor.getInt(1)).isEqualTo(raw.rank);
195         // Data Title
196         assertThat(cursor.getString(2)).isEqualTo(updatedTitle);
197         // Normalized Title
198         assertThat(cursor.getString(3)).isEqualTo(normalizedTitle);
199         // Summary On
200         assertThat(cursor.getString(4)).isEqualTo(updatedSummaryOn);
201         // Summary On Normalized
202         assertThat(cursor.getString(5)).isEqualTo(normalizedSummaryOn);
203         // Summary Off
204         assertThat(cursor.getString(6)).isEqualTo(updatedSummaryOff);
205         // Summary off normalized
206         assertThat(cursor.getString(7)).isEqualTo(normalizedSummaryOff);
207         // Entries
208         assertThat(cursor.getString(8)).isEqualTo(raw.entries);
209         // Keywords
210         assertThat(cursor.getString(9)).isEqualTo(spaceDelimittedKeywords);
211         // Screen Title
212         assertThat(cursor.getString(10)).isEqualTo(raw.screenTitle);
213         // Class Name
214         assertThat(cursor.getString(11)).isEqualTo(raw.className);
215         // Icon
216         assertThat(cursor.getInt(12)).isEqualTo(raw.iconResId);
217         // Intent Action
218         assertThat(cursor.getString(13)).isEqualTo(raw.intentAction);
219         // Target Package
220         assertThat(cursor.getString(14)).isEqualTo(raw.intentTargetPackage);
221         // Target Class
222         assertThat(cursor.getString(15)).isEqualTo(raw.intentTargetClass);
223         // Enabled
224         assertThat(cursor.getInt(16) == 1).isEqualTo(raw.enabled);
225         // Data ref key
226         assertThat(cursor.getString(17)).isNotNull();
227         // User Id
228         assertThat(cursor.getInt(18)).isEqualTo(raw.userId);
229         // Payload Type - default is 0
230         assertThat(cursor.getInt(19)).isEqualTo(0);
231         // Payload
232         assertThat(cursor.getBlob(20)).isNull();
233     }
234 
235     @Test
testInsertRawColumn_mismatchedLocale_noRowInserted()236     public void testInsertRawColumn_mismatchedLocale_noRowInserted() {
237         SearchIndexableRaw raw = getFakeRaw("ca-fr");
238         mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
239         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
240         assertThat(cursor.getCount()).isEqualTo(0);
241     }
242 
243     // Tests for the flow: IndexOneResource -> IndexFromResource ->
244     //                     UpdateOneRowWithFilteredData -> UpdateOneRow
245 
246     @Test
testNullResource_NothingInserted()247     public void testNullResource_NothingInserted() {
248         mManager.indexOneSearchIndexableData(mDb, localeStr, null /* searchIndexableResource */,
249                 new HashMap<>());
250         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
251         assertThat(cursor.getCount()).isEqualTo(0);
252     }
253 
254     @Test
testAddResource_RowsInserted()255     public void testAddResource_RowsInserted() {
256         SearchIndexableResource resource = getFakeResource(R.xml.display_settings);
257         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
258         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
259         assertThat(cursor.getCount()).isEqualTo(18);
260     }
261 
262     @Test
testAddResource_withNIKs_rowsInsertedDisabled()263     public void testAddResource_withNIKs_rowsInsertedDisabled() {
264         SearchIndexableResource resource = getFakeResource(R.xml.display_settings);
265         // Only add 2 of 16 items to be disabled.
266         String[] keys = {"brightness", "wallpaper"};
267         Map<String, Set<String>> niks = getNonIndexableKeys(keys);
268 
269         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, niks);
270 
271         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
272         assertThat(cursor.getCount()).isEqualTo(2);
273         cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
274         assertThat(cursor.getCount()).isEqualTo(16);
275     }
276 
277     @Test
testAddResourceHeader_rowsMatch()278     public void testAddResourceHeader_rowsMatch() {
279         SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
280         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
281 
282         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
283         cursor.moveToPosition(1);
284 
285         // Locale
286         assertThat(cursor.getString(0)).isEqualTo(localeStr);
287         // Data Rank
288         assertThat(cursor.getInt(1)).isEqualTo(rank);
289         // Data Title
290         assertThat(cursor.getString(2)).isEqualTo("App info");
291         // Normalized Title
292         assertThat(cursor.getString(3)).isEqualTo("app info");
293         // Summary On
294         assertThat(cursor.getString(4)).isEqualTo("Manage apps, set up quick launch shortcuts");
295         // Summary On Normalized
296         assertThat(cursor.getString(5)).isEqualTo("manage apps, set up quick launch shortcuts");
297         // Summary Off - only on for checkbox preferences
298         assertThat(cursor.getString(6)).isEmpty();
299         // Summary off normalized - only on for checkbox preferences
300         assertThat(cursor.getString(7)).isEmpty();
301         // Entries - only on for list preferences
302         assertThat(cursor.getString(8)).isNull();
303         // Keywords
304         assertThat(cursor.getString(9)).isEmpty();
305         // Screen Title
306         assertThat(cursor.getString(10)).isEqualTo("App info");
307         // Class Name
308         assertThat(cursor.getString(11)).isEqualTo(className);
309         // Icon
310         assertThat(cursor.getInt(12)).isEqualTo(0);
311         // Intent Action
312         assertThat(cursor.getString(13)).isEqualTo(action);
313         // Target Package
314         assertThat(cursor.getString(14)).isEqualTo(targetPackage);
315         // Target Class
316         assertThat(cursor.getString(15)).isEqualTo(targetClass);
317         // Enabled
318         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
319         // Data ref key
320         assertThat(cursor.getString(17)).isEqualTo("applications_settings");
321         // User Id
322         assertThat(cursor.getInt(18)).isEqualTo(userId);
323         // Payload Type - default is 0
324         assertThat(cursor.getInt(19)).isEqualTo(0);
325         // Payload - should be updated to real payloads as controllers are added
326         assertThat(cursor.getBlob(20)).isNull();
327     }
328 
329     @Test
testAddResource_withChildFragment_shouldUpdateSiteMapDb()330     public void testAddResource_withChildFragment_shouldUpdateSiteMapDb() {
331         // FIXME: This test was failing. (count = 6 at the end)
332 
333 //        SearchIndexableResource resource = getFakeResource(R.xml.network_and_internet);
334 //        mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
335 //                new HashMap<>());
336 //        Cursor query = mDb.query(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, SITE_MAP_COLUMNS,
337 //                null, null, null, null, null);
338 //        query.moveToPosition(-1);
339 //        int count = 0;
340 //        while (query.moveToNext()) {
341 //            count++;
342 //            assertThat(query.getString(query.getColumnIndex(SiteMapColumns.PARENT_CLASS)))
343 //                    .isEqualTo(className);
344 //            assertThat(query.getString(query.getColumnIndex(SiteMapColumns.PARENT_TITLE)))
345 //                    .isEqualTo(mContext.getString(R.string.network_dashboard_title));
346 //            assertThat(query.getString(query.getColumnIndex(SiteMapColumns.CHILD_CLASS)))
347 //                    .isNotEmpty();
348 //            assertThat(query.getString(query.getColumnIndex(SiteMapColumns.CHILD_TITLE)))
349 //                    .isNotEmpty();
350 //        }
351 //        assertThat(count).isEqualTo(5);
352     }
353 
354     @Test
testAddResource_customSetting_rowsMatch()355     public void testAddResource_customSetting_rowsMatch() {
356         SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
357         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
358         final String prefTitle =
359                 mContext.getString(R.string.fingerprint_swipe_for_notifications_title);
360         final String prefSummary =
361                 mContext.getString(R.string.fingerprint_swipe_for_notifications_summary);
362         Cursor cursor = mDb.rawQuery(
363                 "SELECT * FROM prefs_index where data_title='" + prefTitle + "'", null);
364         cursor.moveToFirst();
365 
366         // Locale
367         assertThat(cursor.getString(0)).isEqualTo(localeStr);
368         // Data Rank
369         assertThat(cursor.getInt(1)).isEqualTo(rank);
370         // Data Title
371         assertThat(cursor.getString(2)).isEqualTo(prefTitle);
372         // Normalized Title
373         assertThat(cursor.getString(3)).isEqualTo(prefTitle.toLowerCase());
374         // Summary On
375         assertThat(cursor.getString(4)).isEqualTo(prefSummary);
376         // Summary On Normalized
377         assertThat(cursor.getString(5)).isEqualTo(prefSummary.toLowerCase());
378         // Summary Off - only on for checkbox preferences
379         assertThat(cursor.getString(6)).isEmpty();
380         // Summary off normalized - only on for checkbox preferences
381         assertThat(cursor.getString(7)).isEmpty();
382         // Entries - only on for list preferences
383         assertThat(cursor.getString(8)).isNull();
384         // Keywords
385         assertThat(cursor.getString(9)).isEmpty();
386         // Screen Title
387         assertThat(cursor.getString(10)).isEqualTo(
388                 mContext.getString(R.string.fingerprint_swipe_for_notifications_title));
389         // Class Name
390         assertThat(cursor.getString(11)).isEqualTo(className);
391         // Icon
392         assertThat(cursor.getInt(12)).isEqualTo(noIcon);
393         // Intent Action
394         assertThat(cursor.getString(13)).isEqualTo(action);
395         // Target Package
396         assertThat(cursor.getString(14)).isEqualTo(targetPackage);
397         // Target Class
398         assertThat(cursor.getString(15)).isEqualTo(targetClass);
399         // Enabled
400         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
401         // Data ref key
402         assertThat(cursor.getString(17)).isEqualTo("gesture_swipe_down_fingerprint");
403         // User Id
404         assertThat(cursor.getInt(18)).isEqualTo(userId);
405         // Payload Type - default is 0
406         assertThat(cursor.getInt(19)).isEqualTo(0);
407         // Payload - should be updated to real payloads as controllers are added
408         assertThat(cursor.getBlob(20)).isNull();
409     }
410 
411     @Test
testAddResource_checkboxPreference_rowsMatch()412     public void testAddResource_checkboxPreference_rowsMatch() {
413         SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
414         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
415 
416         /* Should return 6 results, with the following titles:
417          * Advanced Settings, Apps, Manage Apps, Preferred install location, Running Services
418          */
419         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
420         cursor.moveToPosition(0);
421         // Locale
422         assertThat(cursor.getString(0)).isEqualTo(localeStr);
423         // Data Rank
424         assertThat(cursor.getInt(1)).isEqualTo(rank);
425         // Data Title
426         assertThat(cursor.getString(2)).isEqualTo("Advanced settings");
427         // Normalized Title
428         assertThat(cursor.getString(3)).isEqualTo("advanced settings");
429         // Summary On
430         assertThat(cursor.getString(4)).isEqualTo("Enable more settings options");
431         // Summary On Normalized
432         assertThat(cursor.getString(5)).isEqualTo("enable more settings options");
433         // Summary Off
434         assertThat(cursor.getString(6)).isEqualTo("Enable more settings options");
435         // Summary Off
436         assertThat(cursor.getString(7)).isEqualTo("enable more settings options");
437         // Entries - only on for list preferences
438         assertThat(cursor.getString(8)).isNull();
439         // Keywords
440         assertThat(cursor.getString(9)).isEmpty();
441         // Screen Title
442         assertThat(cursor.getString(10)).isEqualTo("App info");
443         // Class Name
444         assertThat(cursor.getString(11)).isEqualTo(className);
445         // Icon
446         assertThat(cursor.getInt(12)).isEqualTo(noIcon);
447         // Intent Action
448         assertThat(cursor.getString(13)).isEqualTo(action);
449         // Target Package
450         assertThat(cursor.getString(14)).isEqualTo(targetPackage);
451         // Target Class
452         assertThat(cursor.getString(15)).isEqualTo(targetClass);
453         // Enabled
454         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
455         // Data ref key
456         assertThat(cursor.getString(17)).isEqualTo("toggle_advanced_settings");
457         // User Id
458         assertThat(cursor.getInt(18)).isEqualTo(userId);
459         // Payload Type - default is 0
460         assertThat(cursor.getInt(19)).isEqualTo(0);
461         // Payload - should be updated to real payloads as controllers are added
462         assertThat(cursor.getBlob(20)).isNull();
463     }
464 
465     @Test
testAddResource_listPreference_rowsMatch()466     public void testAddResource_listPreference_rowsMatch() {
467         SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
468         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
469 
470         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
471         cursor.moveToPosition(3);
472         // Locale
473         assertThat(cursor.getString(0)).isEqualTo(localeStr);
474         // Data Rank
475         assertThat(cursor.getInt(1)).isEqualTo(rank);
476         // Data Title
477         assertThat(cursor.getString(2)).isEqualTo("Preferred install location");
478         // Normalized Title
479         assertThat(cursor.getString(3)).isEqualTo("preferred install location");
480         // Summary On
481         assertThat(cursor.getString(4)).isEqualTo(
482                 "Change the preferred installation location for new apps");
483         // Summary On Normalized
484         assertThat(cursor.getString(5)).isEqualTo(
485                 "change the preferred installation location for new apps");
486         // Summary Off - only on for checkbox preferences
487         assertThat(cursor.getString(6)).isEmpty();
488         // Summary off normalized - only on for checkbox preferences
489         assertThat(cursor.getString(7)).isEmpty();
490         // Entries - only on for list preferences
491         assertThat(cursor.getString(8)).isEqualTo("Internal device storage|Removable SD card|" +
492                 "Let the system decide|");
493         // Keywords
494         assertThat(cursor.getString(9)).isEmpty();
495         // Screen Title
496         assertThat(cursor.getString(10)).isEqualTo("App info");
497         // Class Name
498         assertThat(cursor.getString(11)).isEqualTo(className);
499         // Icon
500         assertThat(cursor.getInt(12)).isEqualTo(noIcon);
501         // Intent Action
502         assertThat(cursor.getString(13)).isEqualTo(action);
503         // Target Package
504         assertThat(cursor.getString(14)).isEqualTo(targetPackage);
505         // Target Class
506         assertThat(cursor.getString(15)).isEqualTo(targetClass);
507         // Enabled
508         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
509         // Data ref key
510         assertThat(cursor.getString(17)).isEqualTo("app_install_location");
511         // User Id
512         assertThat(cursor.getInt(18)).isEqualTo(userId);
513         // Payload Type - default is 0
514         assertThat(cursor.getInt(19)).isEqualTo(0);
515         // Payload - should be updated to real payloads as controllers are added
516         assertThat(cursor.getBlob(20)).isNull();
517     }
518 
519     @Test
testAddResource_iconAddedFromXml()520     public void testAddResource_iconAddedFromXml() {
521         SearchIndexableResource resource = getFakeResource(R.xml.connected_devices);
522         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
523 
524         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
525         cursor.moveToPosition(0);
526 
527         // Icon
528         assertThat(cursor.getInt(12)).isNotEqualTo(noIcon);
529     }
530 
531     // Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
532     //                     UpdateOneRowWithFilteredData -> UpdateOneRow
533 
534     @Test
testResourceProvider_rowInserted()535     public void testResourceProvider_rowInserted() {
536         SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
537         resource.xmlResId = 0;
538         resource.className = "com.android.settings.display.ScreenZoomSettings";
539 
540         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
541         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
542         assertThat(cursor.getCount()).isEqualTo(1);
543     }
544 
545     @Test
testResourceProvider_rowMatches()546     public void testResourceProvider_rowMatches() {
547         SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
548         resource.xmlResId = 0;
549         resource.className = "com.android.settings.display.ScreenZoomSettings";
550 
551         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
552         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
553         cursor.moveToPosition(0);
554 
555         // Locale
556         assertThat(cursor.getString(0)).isEqualTo(localeStr);
557         // Data Rank
558         assertThat(cursor.getInt(1)).isEqualTo(rank);
559         // Data Title
560         assertThat(cursor.getString(2)).isEqualTo("Display size");
561         // Normalized Title
562         assertThat(cursor.getString(3)).isEqualTo("display size");
563         // Summary On
564         assertThat(cursor.getString(4)).isEmpty();
565         // Summary On Normalized
566         assertThat(cursor.getString(5)).isEmpty();
567         // Summary Off - only on for checkbox preferences
568         assertThat(cursor.getString(6)).isEmpty();
569         // Summary off normalized - only on for checkbox preferences
570         assertThat(cursor.getString(7)).isEmpty();
571         // Entries - only on for list preferences
572         assertThat(cursor.getString(8)).isNull();
573         // Keywords
574         assertThat(cursor.getString(9)).isEqualTo("display density screen zoom scale scaling");
575         // Screen Title
576         assertThat(cursor.getString(10)).isEqualTo("Display size");
577         // Class Name
578         assertThat(cursor.getString(11))
579                 .isEqualTo("com.android.settings.display.ScreenZoomSettings");
580         // Icon
581         assertThat(cursor.getInt(12)).isEqualTo(noIcon);
582         // Intent Action
583         assertThat(cursor.getString(13)).isNull();
584         // Target Package
585         assertThat(cursor.getString(14)).isNull();
586         // Target Class
587         assertThat(cursor.getString(15)).isNull();
588         // Enabled
589         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
590         // Data ref key
591         assertThat(cursor.getString(17)).isNull();
592         // User Id
593         assertThat(cursor.getInt(18)).isEqualTo(userId);
594         // Payload Type - default is 0
595         assertThat(cursor.getInt(19)).isEqualTo(0);
596         // Payload - should be updated to real payloads as controllers are added
597         assertThat(cursor.getBlob(20)).isNull();
598     }
599 
600     @Test
testResourceProvider_resourceRowInserted()601     public void testResourceProvider_resourceRowInserted() {
602         SearchIndexableResource resource = getFakeResource(0);
603         resource.className = "com.android.settings.LegalSettings";
604 
605         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
606         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
607         assertThat(cursor.getCount()).isEqualTo(6);
608     }
609 
610     @Test
testResourceProvider_resourceRowMatches()611     public void testResourceProvider_resourceRowMatches() {
612         SearchIndexableResource resource = getFakeResource(0);
613         resource.className = "com.android.settings.display.ScreenZoomSettings";
614 
615         mManager.indexOneSearchIndexableData(mDb, localeStr, resource, new HashMap<>());
616         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
617         cursor.moveToPosition(0);
618 
619         // Locale
620         assertThat(cursor.getString(0)).isEqualTo(localeStr);
621         // Data Rank
622         assertThat(cursor.getInt(1)).isEqualTo(rank);
623         // Data Title
624         assertThat(cursor.getString(2)).isEqualTo("Display size");
625         // Normalized Title
626         assertThat(cursor.getString(3)).isEqualTo("display size");
627         // Summary On
628         assertThat(cursor.getString(4)).isEmpty();
629         // Summary On Normalized
630         assertThat(cursor.getString(5)).isEmpty();
631         // Summary Off - only on for checkbox preferences
632         assertThat(cursor.getString(6)).isEmpty();
633         // Summary off normalized - only on for checkbox preferences
634         assertThat(cursor.getString(7)).isEmpty();
635         // Entries - only on for list preferences
636         assertThat(cursor.getString(8)).isNull();
637         // Keywords
638         assertThat(cursor.getString(9)).isEqualTo(
639                 "display density screen zoom scale scaling");
640         // Screen Title
641         assertThat(cursor.getString(10)).isEqualTo("Display size");
642         // Class Name
643         assertThat(cursor.getString(11))
644                 .isEqualTo("com.android.settings.display.ScreenZoomSettings");
645         // Icon
646         assertThat(cursor.getInt(12)).isEqualTo(noIcon);
647         // Intent Action
648         assertThat(cursor.getString(13)).isNull();
649         // Target Package
650         assertThat(cursor.getString(14)).isNull();
651         // Target Class
652         assertThat(cursor.getString(15)).isNull();
653         // Enabled
654         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
655         // Data ref key
656         assertThat(cursor.getString(17)).isNull();
657         // User Id
658         assertThat(cursor.getInt(18)).isEqualTo(userId);
659         // Payload Type - default is 0
660         assertThat(cursor.getInt(19)).isEqualTo(0);
661         // Payload - should be updated to real payloads as controllers are added
662         assertThat(cursor.getBlob(20)).isNull();
663     }
664 
665     @Test
testResourceProvider_disabledResource_rowsInserted()666     public void testResourceProvider_disabledResource_rowsInserted() {
667         SearchIndexableResource resource = getFakeResource(0);
668         resource.className = "com.android.settings.LegalSettings";
669 
670         mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
671                 new HashMap<String, Set<String>>());
672 
673         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
674         assertThat(cursor.getCount()).isEqualTo(1);
675         cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
676         assertThat(cursor.getCount()).isEqualTo(5);
677     }
678 
679     @Test
testResource_withTitleAndSettingName_titleNotInserted()680     public void testResource_withTitleAndSettingName_titleNotInserted() {
681         SearchIndexableResource resource = getFakeResource(R.xml.swipe_to_notification_settings);
682         mManager.indexFromResource(mDb, localeStr, resource, new ArrayList<String>());
683 
684         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE" +
685                 " enabled = 1", null);
686         assertThat(cursor.getCount()).isEqualTo(1);
687     }
688 
689     // Test new public indexing flow
690 
691     @Test
692     @Config(shadows = {ShadowDatabaseIndexingUtils.class,})
testPerformIndexing_fullIndex_getsDataFromProviders()693     public void testPerformIndexing_fullIndex_getsDataFromProviders() {
694         DummyProvider provider = new DummyProvider();
695         provider.onCreate();
696         ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
697 
698         // Test that Indexables are added for Full indexing
699         when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
700                 .thenReturn(getDummyResolveInfo());
701 
702         DatabaseIndexingManager manager =
703                 spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
704         doReturn(true).when(manager).isFullIndex(anyString(), anyString());
705 
706         manager.performIndexing();
707 
708         verify(manager).addIndexablesFromRemoteProvider(PACKAGE_ONE, AUTHORITY_ONE);
709         verify(manager).updateDatabase(true /* isFullIndex */, Locale.getDefault().toString());
710     }
711 
712     @Test
713     @Config(shadows = {ShadowDatabaseIndexingUtils.class,})
testPerformIndexing_incrementalIndex_noDataAdded()714     public void testPerformIndexing_incrementalIndex_noDataAdded() {
715         DummyProvider provider = new DummyProvider();
716         provider.onCreate();
717         ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
718 
719         // Test that Indexables are added for Full indexing
720         when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
721                 .thenReturn(getDummyResolveInfo());
722 
723         DatabaseIndexingManager manager =
724                 spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
725         doReturn(false).when(manager).isFullIndex(anyString(), anyString());
726 
727         manager.mDataToProcess.dataToUpdate.clear();
728 
729         manager.performIndexing();
730 
731         verify(manager, times(0)).addDataToDatabase(any(SQLiteDatabase.class), anyString(),
732                 anyList(), anyMap());
733         verify(manager, times(0)).addIndexablesFromRemoteProvider(PACKAGE_ONE, AUTHORITY_ONE);
734         verify(manager).updateDataInDatabase(any(SQLiteDatabase.class), anyMap());
735     }
736 
737     @Test
738     @Config(shadows = {ShadowDatabaseIndexingUtils.class,})
testPerformIndexing_localeChanged_databaseDropped()739     public void testPerformIndexing_localeChanged_databaseDropped() {
740         DummyProvider provider = new DummyProvider();
741         provider.onCreate();
742         ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
743 
744         // Test that Indexables are added for Full indexing
745         when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
746                 .thenReturn(getDummyResolveInfo());
747 
748         // Initialize the Manager
749         DatabaseIndexingManager manager =
750                 spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
751         doReturn(true).when(manager).isFullIndex(anyString(), anyString());
752 
753         // Insert data point which will be dropped
754         final String oldTitle = "This is French";
755         insertSpecialCase(oldTitle, true, "key");
756 
757         // Add a data point to be added by the indexing
758         SearchIndexableRaw raw = new SearchIndexableRaw(mContext);
759         final String newTitle = "This is English";
760         raw.title = newTitle;
761         manager.mDataToProcess.dataToUpdate.add(raw);
762 
763         manager.performIndexing();
764 
765         // Assert that the New Title is inserted
766         final Cursor newCursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE data_title = '" +
767                 newTitle + "'", null);
768         assertThat(newCursor.getCount()).isEqualTo(1);
769 
770         // Assert that the Old Title is no longer in the database, since it was dropped
771         final Cursor oldCursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE data_title = '" +
772                 oldTitle + "'", null);
773         assertThat(oldCursor.getCount()).isEqualTo(0);
774     }
775 
776     @Test
777     @Config(shadows = {ShadowDatabaseIndexingUtils.class,})
testPerformIndexing_onOta_FullIndex()778     public void testPerformIndexing_onOta_FullIndex() {
779         DummyProvider provider = new DummyProvider();
780         provider.onCreate();
781         ShadowContentResolver.registerProvider(
782                 AUTHORITY_ONE, provider
783         );
784 
785         // Test that Indexables are added for Full indexing
786         when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
787                 .thenReturn(getDummyResolveInfo());
788 
789         DatabaseIndexingManager manager =
790                 spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
791         doReturn(true).when(manager).isFullIndex(anyString(), anyString());
792 
793         manager.performIndexing();
794 
795         verify(manager).updateDatabase(true /* isFullIndex */, Locale.getDefault().toString());
796     }
797 
798     @Test
799     @Config(shadows = {ShadowDatabaseIndexingUtils.class,})
testPerformIndexing_onOta_buildNumberIsCached()800     public void testPerformIndexing_onOta_buildNumberIsCached() {
801         DummyProvider provider = new DummyProvider();
802         provider.onCreate();
803         ShadowContentResolver.registerProvider(
804                 AUTHORITY_ONE, provider
805         );
806 
807         // Test that Indexables are added for Full indexing
808         when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
809                 .thenReturn(getDummyResolveInfo());
810 
811         DatabaseIndexingManager manager =
812                 spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
813         doReturn(true).when(manager).isFullIndex(anyString(), anyString());
814 
815         manager.performIndexing();
816 
817         assertThat(IndexDatabaseHelper.getInstance(mContext).isBuildIndexed(mContext,
818                 Build.FINGERPRINT)).isTrue();
819     }
820 
821     @Test
testFullUpdatedDatabase_noData_addDataToDatabaseNotCalled()822     public void testFullUpdatedDatabase_noData_addDataToDatabaseNotCalled() {
823         mManager.updateDatabase(true /* isFullIndex */, localeStr);
824         mManager.mDataToProcess.dataToUpdate.clear();
825         verify(mManager, times(0)).addDataToDatabase(any(SQLiteDatabase.class), anyString(),
826                 anyList(), anyMap());
827     }
828 
829     @Test
testFullUpdatedDatabase_updatedDataInDatabaseNotCalled()830     public void testFullUpdatedDatabase_updatedDataInDatabaseNotCalled() {
831         mManager.updateDatabase(true /* isFullIndex */, localeStr);
832         verify(mManager, times(0)).updateDataInDatabase(any(SQLiteDatabase.class), anyMap());
833     }
834 
835     @Test
testLocaleUpdated_afterIndexing_localeNotAdded()836     public void testLocaleUpdated_afterIndexing_localeNotAdded() {
837         mManager.updateDatabase(true /* isFullIndex */, localeStr);
838         assertThat(IndexDatabaseHelper.getInstance(mContext)
839                 .isLocaleAlreadyIndexed(mContext, localeStr)).isFalse();
840     }
841 
842     @Test
testLocaleUpdated_afterFullIndexing_localeAdded()843     public void testLocaleUpdated_afterFullIndexing_localeAdded() {
844         mManager.performIndexing();
845         assertThat(IndexDatabaseHelper.getInstance(mContext)
846                 .isLocaleAlreadyIndexed(mContext, localeStr)).isTrue();
847     }
848 
849     @Test
testUpdateDatabase_newEligibleData_addedToDatabase()850     public void testUpdateDatabase_newEligibleData_addedToDatabase() {
851         // Test that addDataToDatabase is called when dataToUpdate is non-empty
852         mManager.mDataToProcess.dataToUpdate.add(getFakeRaw());
853         mManager.updateDatabase(true /* isFullIndex */, localeStr);
854 
855         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
856         cursor.moveToPosition(0);
857 
858         // Locale
859         assertThat(cursor.getString(0)).isEqualTo(localeStr);
860         // Data Rank
861         assertThat(cursor.getInt(1)).isEqualTo(rank);
862         // Data Title
863         assertThat(cursor.getString(2)).isEqualTo(updatedTitle);
864         // Normalized Title
865         assertThat(cursor.getString(3)).isEqualTo(normalizedTitle);
866         // Summary On
867         assertThat(cursor.getString(4)).isEqualTo(updatedSummaryOn);
868         // Summary On Normalized
869         assertThat(cursor.getString(5)).isEqualTo(normalizedSummaryOn);
870         // Summary Off
871         assertThat(cursor.getString(6)).isEqualTo(updatedSummaryOff);
872         // Summary off normalized
873         assertThat(cursor.getString(7)).isEqualTo(normalizedSummaryOff);
874         // Entries
875         assertThat(cursor.getString(8)).isEqualTo(entries);
876         // Keywords
877         assertThat(cursor.getString(9)).isEqualTo(spaceDelimittedKeywords);
878         // Screen Title
879         assertThat(cursor.getString(10)).isEqualTo(screenTitle);
880         // Class Name
881         assertThat(cursor.getString(11)).isEqualTo(className);
882         // Icon
883         assertThat(cursor.getInt(12)).isEqualTo(iconResId);
884         // Intent Action
885         assertThat(cursor.getString(13)).isEqualTo(action);
886         // Target Package
887         assertThat(cursor.getString(14)).isEqualTo(targetPackage);
888         // Target Class
889         assertThat(cursor.getString(15)).isEqualTo(targetClass);
890         // Enabled
891         assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
892         // Data ref key
893         assertThat(cursor.getString(17)).isNotNull();
894         // User Id
895         assertThat(cursor.getInt(18)).isEqualTo(userId);
896         // Payload Type - default is 0
897         assertThat(cursor.getInt(19)).isEqualTo(0);
898         // Payload
899         assertThat(cursor.getBlob(20)).isNull();
900     }
901 
902     @Test
testUpdateDataInDatabase_enabledResultsAreNonIndexable_becomeDisabled()903     public void testUpdateDataInDatabase_enabledResultsAreNonIndexable_becomeDisabled() {
904         // Both results are enabled, and then TITLE_ONE gets disabled.
905         final boolean enabled = true;
906         insertSpecialCase(TITLE_ONE, enabled, KEY_ONE);
907         insertSpecialCase(TITLE_TWO, enabled, KEY_TWO);
908         Map<String, Set<String>> niks = new ArrayMap<>();
909         Set<String> keys = new HashSet<>();
910         keys.add(KEY_ONE);
911         niks.put(targetPackage, keys);
912 
913         mManager.updateDataInDatabase(mDb, niks);
914 
915         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 0", null);
916         cursor.moveToPosition(0);
917 
918         assertThat(cursor.getString(2)).isEqualTo(TITLE_ONE);
919     }
920 
921     @Test
testUpdateDataInDatabase_disabledResultsAreIndexable_becomeEnabled()922     public void testUpdateDataInDatabase_disabledResultsAreIndexable_becomeEnabled() {
923         // Both results are initially disabled, and then TITLE_TWO gets enabled.
924         final boolean enabled = false;
925         insertSpecialCase(TITLE_ONE, enabled, KEY_ONE);
926         insertSpecialCase(TITLE_TWO, enabled, KEY_TWO);
927         Map<String, Set<String>> niks = new ArrayMap<>();
928         Set<String> keys = new HashSet<>();
929         keys.add(KEY_ONE);
930         niks.put(targetPackage, keys);
931 
932         mManager.updateDataInDatabase(mDb, niks);
933 
934         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
935         cursor.moveToPosition(0);
936 
937         assertThat(cursor.getString(2)).isEqualTo(TITLE_TWO);
938     }
939 
940     @Test
941     @Config(shadows = {ShadowContentResolver.class})
testEmptyNonIndexableKeys_emptyDataKeyResources_addedToDatabase()942     public void testEmptyNonIndexableKeys_emptyDataKeyResources_addedToDatabase() {
943         insertSpecialCase(TITLE_ONE, true /* enabled */, null /* dataReferenceKey */);
944 
945         mManager.updateDatabase(false, localeStr);
946 
947         Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
948         cursor.moveToPosition(0);
949         assertThat(cursor.getCount()).isEqualTo(1);
950         assertThat(cursor.getString(2)).isEqualTo(TITLE_ONE);
951     }
952 
953     @Test
testUpdateAsyncTask_onPostExecute_performsCallback()954     public void testUpdateAsyncTask_onPostExecute_performsCallback() {
955         IndexingCallback callback = mock(IndexingCallback.class);
956 
957         DatabaseIndexingManager.IndexingTask task = mManager.new IndexingTask(callback);
958         task.execute();
959 
960         Robolectric.flushForegroundThreadScheduler();
961 
962         verify(callback).onIndexingFinished();
963     }
964 
965     @Test
testUpdateAsyncTask_onPostExecute_setsIndexingComplete()966     public void testUpdateAsyncTask_onPostExecute_setsIndexingComplete() {
967         SearchFeatureProviderImpl provider = new SearchFeatureProviderImpl();
968         DatabaseIndexingManager manager = spy(provider.getIndexingManager(mContext));
969         DatabaseIndexingManager.IndexingTask task = manager.new IndexingTask(null);
970         doNothing().when(manager).performIndexing();
971 
972         task.execute();
973         Robolectric.flushForegroundThreadScheduler();
974 
975         assertThat(provider.isIndexingComplete(mContext)).isTrue();
976     }
977 
978     // Util functions
979 
getFakeRaw()980     private SearchIndexableRaw getFakeRaw() {
981         return getFakeRaw(localeStr);
982     }
983 
getFakeRaw(String localeStr)984     private SearchIndexableRaw getFakeRaw(String localeStr) {
985         SearchIndexableRaw data = new SearchIndexableRaw(mContext);
986         data.locale = new Locale(localeStr);
987         data.rank = rank;
988         data.title = title;
989         data.summaryOn = summaryOn;
990         data.summaryOff = summaryOff;
991         data.entries = entries;
992         data.keywords = keywords;
993         data.screenTitle = screenTitle;
994         data.className = className;
995         data.packageName = packageName;
996         data.iconResId = iconResId;
997         data.intentAction = action;
998         data.intentTargetPackage = targetPackage;
999         data.intentTargetClass = targetClass;
1000         data.key = key;
1001         data.userId = userId;
1002         data.enabled = enabled;
1003         return data;
1004     }
1005 
getFakeResource(int xml)1006     private SearchIndexableResource getFakeResource(int xml) {
1007         SearchIndexableResource sir = new SearchIndexableResource(mContext);
1008         sir.rank = rank;
1009         sir.xmlResId = xml;
1010         sir.className = className;
1011         sir.packageName = packageName;
1012         sir.iconResId = iconResId;
1013         sir.intentAction = action;
1014         sir.intentTargetPackage = targetPackage;
1015         sir.intentTargetClass = targetClass;
1016         sir.enabled = enabled;
1017         return sir;
1018     }
1019 
getNonIndexableKeys(String[] keys)1020     private Map<String, Set<String>> getNonIndexableKeys(String[] keys) {
1021         Map<String, Set<String>> niks = new HashMap<>();
1022         Set<String> keysList = new HashSet<>();
1023         keysList.addAll(Arrays.asList(keys));
1024         niks.put(packageName, keysList);
1025         return niks;
1026     }
1027 
getDummyResolveInfo()1028     private List<ResolveInfo> getDummyResolveInfo() {
1029         List<ResolveInfo> infoList = new ArrayList<>();
1030         ResolveInfo info = new ResolveInfo();
1031         info.providerInfo = new ProviderInfo();
1032         info.providerInfo.exported = true;
1033         info.providerInfo.authority = AUTHORITY_ONE;
1034         info.providerInfo.packageName = PACKAGE_ONE;
1035         infoList.add(info);
1036 
1037         return infoList;
1038     }
1039 
1040     // TODO move this method and its counterpart in CursorToSearchResultConverterTest into
1041     // a util class with public fields to assert values.
getDummyCursor()1042     private Cursor getDummyCursor() {
1043         MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
1044         final String BLANK = "";
1045 
1046         ArrayList<String> item =
1047                 new ArrayList<>(INDEXABLES_RAW_COLUMNS.length);
1048         item.add("42"); // Rank
1049         item.add(TITLE_ONE); // Title
1050         item.add(BLANK); // Summary on
1051         item.add(BLANK); // summary off
1052         item.add(BLANK); // entries
1053         item.add(BLANK); // keywords
1054         item.add(BLANK); // screen title
1055         item.add(BLANK); // classname
1056         item.add("123"); // Icon
1057         item.add(BLANK); // Intent action
1058         item.add(BLANK); // target package
1059         item.add(BLANK); // target class
1060         item.add(KEY_ONE); // Key
1061         item.add("-1"); // userId
1062         cursor.addRow(item);
1063 
1064         return cursor;
1065     }
1066 
insertSpecialCase(String specialCase, boolean enabled, String key)1067     private void insertSpecialCase(String specialCase, boolean enabled, String key) {
1068 
1069         ContentValues values = new ContentValues();
1070         values.put(IndexDatabaseHelper.IndexColumns.DOCID, specialCase.hashCode());
1071         values.put(IndexDatabaseHelper.IndexColumns.LOCALE, localeStr);
1072         values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
1073         values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, specialCase);
1074         values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, "");
1075         values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, "");
1076         values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, "");
1077         values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, "");
1078         values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, "");
1079         values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, "");
1080         values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, "");
1081         values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, "");
1082         values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves");
1083         values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, "");
1084         values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, targetPackage);
1085         values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, "");
1086         values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
1087         values.put(IndexDatabaseHelper.IndexColumns.ENABLED, enabled);
1088         values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key);
1089         values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
1090         values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
1091         values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, (String) null);
1092 
1093         mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
1094     }
1095 
1096     private class DummyProvider extends ContentProvider {
1097 
1098         @Override
onCreate()1099         public boolean onCreate() {
1100             return false;
1101         }
1102 
1103         @Override
query(@onNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder)1104         public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
1105                 @Nullable String selection, @Nullable String[] selectionArgs,
1106                 @Nullable String sortOrder) {
1107             if (uri.toString().contains("xml")) {
1108                 return null;
1109             }
1110             return getDummyCursor();
1111         }
1112 
1113         @Override
getType(@onNull Uri uri)1114         public String getType(@NonNull Uri uri) {
1115             return null;
1116         }
1117 
1118         @Override
insert(@onNull Uri uri, @Nullable ContentValues values)1119         public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
1120             return null;
1121         }
1122 
1123         @Override
delete(@onNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs)1124         public int delete(@NonNull Uri uri, @Nullable String selection,
1125                 @Nullable String[] selectionArgs) {
1126             return 0;
1127         }
1128 
1129         @Override
update(@onNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs)1130         public int update(@NonNull Uri uri, @Nullable ContentValues values,
1131                 @Nullable String selection, @Nullable String[] selectionArgs) {
1132             return 0;
1133         }
1134     }
1135 }
1136