• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.slices;
19 
20 import static android.content.ContentResolver.SCHEME_CONTENT;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.app.PendingIntent;
35 import android.app.slice.SliceManager;
36 import android.content.ContentResolver;
37 import android.content.ContentValues;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.database.sqlite.SQLiteDatabase;
41 import android.net.Uri;
42 import android.os.StrictMode;
43 import android.provider.Settings;
44 import android.provider.SettingsSlicesContract;
45 import android.util.ArraySet;
46 import android.view.accessibility.AccessibilityManager;
47 
48 import androidx.slice.Slice;
49 import androidx.slice.SliceProvider;
50 import androidx.slice.widget.SliceLiveData;
51 
52 import com.android.settings.R;
53 import com.android.settings.testutils.DatabaseTestUtils;
54 import com.android.settings.testutils.FakeToggleController;
55 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
56 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
57 import com.android.settings.testutils.shadow.ShadowThreadUtils;
58 import com.android.settings.testutils.shadow.ShadowUserManager;
59 import com.android.settings.testutils.shadow.ShadowUtils;
60 import com.android.settings.wifi.slice.WifiScanWorker;
61 import com.android.settingslib.wifi.WifiTracker;
62 
63 import org.junit.After;
64 import org.junit.Before;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.mockito.Mock;
68 import org.mockito.MockitoAnnotations;
69 import org.robolectric.Robolectric;
70 import org.robolectric.RobolectricTestRunner;
71 import org.robolectric.RuntimeEnvironment;
72 import org.robolectric.annotation.Config;
73 import org.robolectric.annotation.Implementation;
74 import org.robolectric.annotation.Implements;
75 import org.robolectric.annotation.Resetter;
76 import org.robolectric.shadow.api.Shadow;
77 import org.robolectric.shadows.ShadowAccessibilityManager;
78 
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.Collection;
82 import java.util.Collections;
83 import java.util.HashMap;
84 import java.util.HashSet;
85 import java.util.List;
86 import java.util.Set;
87 
88 /**
89  * TODO Investigate using ShadowContentResolver.registerProviderInternal(String, ContentProvider)
90  */
91 @RunWith(RobolectricTestRunner.class)
92 @Config(shadows = {ShadowUserManager.class, ShadowThreadUtils.class, ShadowUtils.class,
93         SlicesDatabaseAccessorTest.ShadowApplicationPackageManager.class,
94         ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class,
95         SettingsSliceProviderTest.ShadowWifiScanWorker.class})
96 public class SettingsSliceProviderTest {
97 
98     private static final String KEY = "KEY";
99     private static final String INTENT_PATH =
100             SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
101     private static final String TITLE = "title";
102     private static final String SUMMARY = "summary";
103     private static final String SCREEN_TITLE = "screen title";
104     private static final String FRAGMENT_NAME = "fragment name";
105     private static final int ICON = R.drawable.ic_settings_accent;
106     private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
107     private static final String PREF_CONTROLLER = FakeToggleController.class.getName();
108 
109     private Context mContext;
110     private SettingsSliceProvider mProvider;
111     @Mock
112     private SliceManager mManager;
113 
114     private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
115             CustomSliceRegistry.WIFI_SLICE_URI,
116             CustomSliceRegistry.BLUETOOTH_URI,
117             CustomSliceRegistry.LOCATION_SLICE_URI
118     );
119 
120     private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
121             CustomSliceRegistry.ZEN_MODE_SLICE_URI,
122             CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
123             CustomSliceRegistry.MOBILE_DATA_SLICE_URI
124     );
125 
126     @Before
setUp()127     public void setUp() {
128         MockitoAnnotations.initMocks(this);
129         mContext = spy(RuntimeEnvironment.application);
130         // Register the fake a11y Service
131         ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract(
132                 RuntimeEnvironment.application.getSystemService(AccessibilityManager.class));
133         shadowAccessibilityManager.setInstalledAccessibilityServiceList(new ArrayList<>());
134 
135         mProvider = spy(new SettingsSliceProvider());
136         ShadowStrictMode.reset();
137         mProvider.mSliceWeakDataCache = new HashMap<>();
138         mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
139         when(mProvider.getContext()).thenReturn(mContext);
140 
141         SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
142 
143         doReturn(mManager).when(mContext).getSystemService(SliceManager.class);
144         when(mManager.getPinnedSlices()).thenReturn(Collections.emptyList());
145 
146         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
147     }
148 
149     @After
cleanUp()150     public void cleanUp() {
151         ShadowThreadUtils.reset();
152         DatabaseTestUtils.clearDb(mContext);
153     }
154 
155     @Test
testInitialSliceReturned_emptySlice()156     public void testInitialSliceReturned_emptySlice() {
157         insertSpecialCase(KEY);
158         final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
159         Slice slice = mProvider.onBindSlice(uri);
160 
161         assertThat(slice.getUri()).isEqualTo(uri);
162         assertThat(slice.getItems()).isEmpty();
163     }
164 
165     @Test
testLoadSlice_returnsSliceFromAccessor()166     public void testLoadSlice_returnsSliceFromAccessor() {
167         insertSpecialCase(KEY);
168         final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
169 
170         mProvider.loadSlice(uri);
171         SliceData data = mProvider.mSliceWeakDataCache.get(uri);
172 
173         assertThat(data.getKey()).isEqualTo(KEY);
174         assertThat(data.getTitle()).isEqualTo(TITLE);
175     }
176 
177     @Test
loadSlice_registersIntentFilter()178     public void loadSlice_registersIntentFilter() {
179         insertSpecialCase(KEY);
180         final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
181 
182         mProvider.loadSlice(uri);
183 
184         verify(mProvider).registerIntentToUri(eq(FakeToggleController.INTENT_FILTER), eq(uri));
185     }
186 
187     @Test
loadSlice_registersBackgroundListener()188     public void loadSlice_registersBackgroundListener() {
189         insertSpecialCase(KEY);
190         final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
191 
192         mProvider.loadSlice(uri);
193 
194         Robolectric.flushForegroundThreadScheduler();
195         Robolectric.flushBackgroundThreadScheduler();
196 
197         assertThat(mProvider.mPinnedWorkers.get(uri).getClass())
198                 .isEqualTo(FakeToggleController.TestWorker.class);
199     }
200 
201     @Test
testLoadSlice_cachedEntryRemovedOnBuild()202     public void testLoadSlice_cachedEntryRemovedOnBuild() {
203         SliceData data = getDummyData();
204         mProvider.mSliceWeakDataCache.put(data.getUri(), data);
205         mProvider.onBindSlice(data.getUri());
206         insertSpecialCase(data.getKey());
207 
208         SliceData cachedData = mProvider.mSliceWeakDataCache.get(data.getUri());
209 
210         assertThat(cachedData).isNull();
211     }
212 
213     @Test
onBindSlice_mainThread_shouldNotOverrideStrictMode()214     public void onBindSlice_mainThread_shouldNotOverrideStrictMode() {
215         ShadowThreadUtils.setIsMainThread(true);
216         final StrictMode.ThreadPolicy oldThreadPolicy = StrictMode.getThreadPolicy();
217         SliceData data = getDummyData();
218         mProvider.mSliceWeakDataCache.put(data.getUri(), data);
219         mProvider.onBindSlice(data.getUri());
220 
221         final StrictMode.ThreadPolicy newThreadPolicy = StrictMode.getThreadPolicy();
222 
223         assertThat(newThreadPolicy.toString()).isEqualTo(oldThreadPolicy.toString());
224     }
225 
226     @Test
227     @Config(shadows = ShadowStrictMode.class)
onBindSlice_backgroundThread_shouldOverrideStrictMode()228     public void onBindSlice_backgroundThread_shouldOverrideStrictMode() {
229         ShadowThreadUtils.setIsMainThread(false);
230 
231         SliceData data = getDummyData();
232         mProvider.mSliceWeakDataCache.put(data.getUri(), data);
233         mProvider.onBindSlice(data.getUri());
234 
235         assertThat(ShadowStrictMode.isThreadPolicyOverridden()).isTrue();
236     }
237 
238     @Test
onBindSlice_requestsBlockedSlice_returnsNull()239     public void onBindSlice_requestsBlockedSlice_returnsNull() {
240         final String blockedKey = "blocked_key";
241         final Set<String> blockedSet = new ArraySet<>();
242         blockedSet.add(blockedKey);
243         doReturn(blockedSet).when(mProvider).getBlockedKeys();
244         final Uri blockedUri = new Uri.Builder()
245                 .scheme(ContentResolver.SCHEME_CONTENT)
246                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
247                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
248                 .appendPath(blockedKey)
249                 .build();
250 
251         final Slice slice = mProvider.onBindSlice(blockedUri);
252 
253         assertThat(slice).isNull();
254     }
255 
256     @Test
getDescendantUris_fullActionUri_returnsSelf()257     public void getDescendantUris_fullActionUri_returnsSelf() {
258         final Uri uri = SliceBuilderUtils.getUri(
259                 SettingsSlicesContract.PATH_SETTING_ACTION + "/key", true);
260 
261         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
262 
263         assertThat(descendants).containsExactly(uri);
264     }
265 
266     @Test
getDescendantUris_fullIntentUri_returnsSelf()267     public void getDescendantUris_fullIntentUri_returnsSelf() {
268         final Uri uri = SliceBuilderUtils.getUri(
269                 SettingsSlicesContract.PATH_SETTING_ACTION + "/key", true);
270 
271         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
272 
273         assertThat(descendants).containsExactly(uri);
274     }
275 
276     @Test
getDescendantUris_wrongPath_returnsEmpty()277     public void getDescendantUris_wrongPath_returnsEmpty() {
278         final Uri uri = SliceBuilderUtils.getUri("invalid_path", true);
279 
280         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
281 
282         assertThat(descendants).isEmpty();
283     }
284 
285     @Test
getDescendantUris_invalidPath_returnsEmpty()286     public void getDescendantUris_invalidPath_returnsEmpty() {
287         final String key = "platform_key";
288         insertSpecialCase(key, true /* isPlatformSlice */);
289         final Uri uri = new Uri.Builder()
290                 .scheme(SCHEME_CONTENT)
291                 .authority(SettingsSlicesContract.AUTHORITY)
292                 .appendPath("invalid")
293                 .build();
294 
295         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
296         descendants.removeAll(SPECIAL_CASE_OEM_URIS);
297 
298         assertThat(descendants).isEmpty();
299     }
300 
301     @Test
getDescendantUris_platformSlice_doesNotReturnOEMSlice()302     public void getDescendantUris_platformSlice_doesNotReturnOEMSlice() {
303         insertSpecialCase("oem_key", false /* isPlatformSlice */);
304         final Uri uri = new Uri.Builder()
305                 .scheme(SCHEME_CONTENT)
306                 .authority(SettingsSlicesContract.AUTHORITY)
307                 .build();
308 
309         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
310         descendants.removeAll(SPECIAL_CASE_PLATFORM_URIS);
311 
312         assertThat(descendants).isEmpty();
313     }
314 
315     @Test
getDescendantUris_oemSlice_doesNotReturnPlatformSlice()316     public void getDescendantUris_oemSlice_doesNotReturnPlatformSlice() {
317         insertSpecialCase("platform_key", true /* isPlatformSlice */);
318         final Uri uri = new Uri.Builder()
319                 .scheme(SCHEME_CONTENT)
320                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
321                 .build();
322 
323         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
324         descendants.removeAll(SPECIAL_CASE_OEM_URIS);
325 
326         assertThat(descendants).isEmpty();
327     }
328 
329     @Test
getDescendantUris_oemSlice_returnsOEMUriDescendant()330     public void getDescendantUris_oemSlice_returnsOEMUriDescendant() {
331         final String key = "oem_key";
332         insertSpecialCase(key, false /* isPlatformSlice */);
333         final Uri uri = new Uri.Builder()
334                 .scheme(SCHEME_CONTENT)
335                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
336                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
337                 .build();
338         final Collection<Uri> expectedUris = new HashSet<>();
339         expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
340         expectedUris.add(new Uri.Builder()
341                 .scheme(SCHEME_CONTENT)
342                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
343                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
344                 .appendPath(key)
345                 .build());
346 
347         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
348 
349         assertThat(descendants).containsExactlyElementsIn(expectedUris);
350     }
351 
352     @Test
getDescendantUris_oemSliceNoPath_returnsOEMUriDescendant()353     public void getDescendantUris_oemSliceNoPath_returnsOEMUriDescendant() {
354         final String key = "oem_key";
355         insertSpecialCase(key, false /* isPlatformSlice */);
356         final Uri uri = new Uri.Builder()
357                 .scheme(SCHEME_CONTENT)
358                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
359                 .build();
360         final Collection<Uri> expectedUris = new HashSet<>();
361         expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
362         expectedUris.add(new Uri.Builder()
363                 .scheme(SCHEME_CONTENT)
364                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
365                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
366                 .appendPath(key)
367                 .build());
368 
369         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
370 
371         assertThat(descendants).containsExactlyElementsIn(expectedUris);
372     }
373 
374     @Test
getDescendantUris_platformSlice_returnsPlatformUriDescendant()375     public void getDescendantUris_platformSlice_returnsPlatformUriDescendant() {
376         final String key = "platform_key";
377         insertSpecialCase(key, true /* isPlatformSlice */);
378         final Uri uri = new Uri.Builder()
379                 .scheme(SCHEME_CONTENT)
380                 .authority(SettingsSlicesContract.AUTHORITY)
381                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
382                 .build();
383         final Collection<Uri> expectedUris = new HashSet<>();
384         expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
385         expectedUris.add(new Uri.Builder()
386                 .scheme(SCHEME_CONTENT)
387                 .authority(SettingsSlicesContract.AUTHORITY)
388                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
389                 .appendPath(key)
390                 .build());
391 
392         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
393 
394         assertThat(descendants).containsExactlyElementsIn(expectedUris);
395     }
396 
397     @Test
getDescendantUris_platformSliceNoPath_returnsPlatformUriDescendant()398     public void getDescendantUris_platformSliceNoPath_returnsPlatformUriDescendant() {
399         final String key = "platform_key";
400         insertSpecialCase(key, true /* isPlatformSlice */);
401         final Uri uri = new Uri.Builder()
402                 .scheme(SCHEME_CONTENT)
403                 .authority(SettingsSlicesContract.AUTHORITY)
404                 .build();
405         final Collection<Uri> expectedUris = new HashSet<>();
406         expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
407         expectedUris.add(new Uri.Builder()
408                 .scheme(SCHEME_CONTENT)
409                 .authority(SettingsSlicesContract.AUTHORITY)
410                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
411                 .appendPath(key)
412                 .build());
413 
414         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
415 
416         assertThat(descendants).containsExactlyElementsIn(expectedUris);
417     }
418 
419     @Test
getDescendantUris_noAuthorityNorPath_returnsAllUris()420     public void getDescendantUris_noAuthorityNorPath_returnsAllUris() {
421         final String platformKey = "platform_key";
422         final String oemKey = "oemKey";
423         insertSpecialCase(platformKey, true /* isPlatformSlice */);
424         insertSpecialCase(oemKey, false /* isPlatformSlice */);
425         final Uri uri = new Uri.Builder()
426                 .scheme(SCHEME_CONTENT)
427                 .build();
428         final Collection<Uri> expectedUris = new HashSet<>();
429         expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
430         expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
431         expectedUris.add(new Uri.Builder()
432                 .scheme(SCHEME_CONTENT)
433                 .authority(SettingsSlicesContract.AUTHORITY)
434                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
435                 .appendPath(platformKey)
436                 .build());
437         expectedUris.add(new Uri.Builder()
438                 .scheme(SCHEME_CONTENT)
439                 .authority(SettingsSliceProvider.SLICE_AUTHORITY)
440                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
441                 .appendPath(oemKey)
442                 .build());
443 
444         final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
445 
446         assertThat(descendants).containsExactlyElementsIn(expectedUris);
447     }
448 
449     @Test
onCreatePermissionRequest_returnsSettingIntent()450     public void onCreatePermissionRequest_returnsSettingIntent() {
451         final PendingIntent pendingIntent = mProvider.onCreatePermissionRequest(
452                 CustomSliceRegistry.FLASHLIGHT_SLICE_URI, "com.android.whaaaat");
453         PendingIntent settingsPendingIntent =
454                 PendingIntent.getActivity(mContext, 0, new Intent(Settings.ACTION_SETTINGS), 0);
455 
456         assertThat(pendingIntent).isEqualTo(settingsPendingIntent);
457     }
458 
459     @Test
bindSlice_wifiSlice_returnsWifiSlice()460     public void bindSlice_wifiSlice_returnsWifiSlice() {
461         final Slice wifiSlice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_SLICE_URI);
462 
463         assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.WIFI_SLICE_URI);
464     }
465 
466     @Test
bindSlice_flashlightSlice_returnsFlashlightSlice()467     public void bindSlice_flashlightSlice_returnsFlashlightSlice() {
468         Settings.Secure.putInt(
469                 mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
470 
471         final Slice flashlightSlice = mProvider.onBindSlice(
472                 CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
473 
474         assertThat(flashlightSlice.getUri()).isEqualTo(CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
475     }
476 
477     @Test
onSlicePinned_noIntentRegistered_specialCaseUri_doesNotCrash()478     public void onSlicePinned_noIntentRegistered_specialCaseUri_doesNotCrash() {
479         final Uri uri = new Uri.Builder()
480                 .scheme(ContentResolver.SCHEME_CONTENT)
481                 .authority(SettingsSlicesContract.AUTHORITY)
482                 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
483                 .appendPath(SettingsSlicesContract.KEY_LOCATION)
484                 .build();
485 
486         mProvider.onSlicePinned(uri);
487     }
488 
489     @Implements(WifiScanWorker.class)
490     public static class ShadowWifiScanWorker {
491         private static WifiTracker mWifiTracker;
492 
493         @Implementation
onSlicePinned()494         protected void onSlicePinned() {
495             mWifiTracker = mock(WifiTracker.class);
496             mWifiTracker.onStart();
497         }
498 
499         @Implementation
onSliceUnpinned()500         protected void onSliceUnpinned() {
501             mWifiTracker.onStop();
502         }
503 
504         @Implementation
close()505         protected void close() {
506             mWifiTracker.onDestroy();
507         }
508 
getWifiTracker()509         static WifiTracker getWifiTracker() {
510             return mWifiTracker;
511         }
512     }
513 
514     @Test
onSlicePinned_backgroundWorker_started()515     public void onSlicePinned_backgroundWorker_started() {
516         mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
517 
518         verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
519     }
520 
521     @Test
onSlicePinned_backgroundWorker_stopped()522     public void onSlicePinned_backgroundWorker_stopped() {
523         mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
524         mProvider.onSliceUnpinned(CustomSliceRegistry.WIFI_SLICE_URI);
525 
526         verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
527     }
528 
529     @Test
shutdown_backgroundWorker_closed()530     public void shutdown_backgroundWorker_closed() {
531         mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
532         mProvider.shutdown();
533 
534         verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
535     }
536 
537     @Test
538     @Config(qualifiers = "mcc998")
grantWhitelistedPackagePermissions_noWhitelist_shouldNotGrant()539     public void grantWhitelistedPackagePermissions_noWhitelist_shouldNotGrant() {
540         final List<Uri> uris = new ArrayList<>();
541         uris.add(Uri.parse("content://settings/slice"));
542 
543         SettingsSliceProvider.grantWhitelistedPackagePermissions(mContext, uris);
544 
545         verify(mManager, never()).grantSlicePermission(anyString(), any(Uri.class));
546     }
547 
548     @Test
549     @Config(qualifiers = "mcc999")
grantWhitelistedPackagePermissions_hasPackageWhitelist_shouldGrant()550     public void grantWhitelistedPackagePermissions_hasPackageWhitelist_shouldGrant() {
551         final List<Uri> uris = new ArrayList<>();
552         uris.add(Uri.parse("content://settings/slice"));
553 
554         SettingsSliceProvider.grantWhitelistedPackagePermissions(mContext, uris);
555 
556         verify(mManager)
557                 .grantSlicePermission("com.android.settings.slice_whitelist_package", uris.get(0));
558     }
559 
insertSpecialCase(String key)560     private void insertSpecialCase(String key) {
561         insertSpecialCase(key, true);
562     }
563 
insertSpecialCase(String key, boolean isPlatformSlice)564     private void insertSpecialCase(String key, boolean isPlatformSlice) {
565         final ContentValues values = new ContentValues();
566         values.put(SlicesDatabaseHelper.IndexColumns.KEY, key);
567         values.put(SlicesDatabaseHelper.IndexColumns.TITLE, TITLE);
568         values.put(SlicesDatabaseHelper.IndexColumns.SUMMARY, "s");
569         values.put(SlicesDatabaseHelper.IndexColumns.SCREENTITLE, "s");
570         values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, R.drawable.ic_settings_accent);
571         values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, "test");
572         values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, PREF_CONTROLLER);
573         values.put(SlicesDatabaseHelper.IndexColumns.PLATFORM_SLICE, isPlatformSlice);
574         values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT);
575         final SQLiteDatabase db = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
576         db.beginTransaction();
577         try {
578             db.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
579             db.setTransactionSuccessful();
580         } finally {
581             db.endTransaction();
582         }
583         db.close();
584     }
585 
getDummyData()586     private static SliceData getDummyData() {
587         return new SliceData.Builder()
588                 .setKey(KEY)
589                 .setTitle(TITLE)
590                 .setSummary(SUMMARY)
591                 .setScreenTitle(SCREEN_TITLE)
592                 .setIcon(ICON)
593                 .setFragmentName(FRAGMENT_NAME)
594                 .setUri(URI)
595                 .setPreferenceControllerClassName(PREF_CONTROLLER)
596                 .build();
597     }
598 
599     @Implements(value = StrictMode.class)
600     public static class ShadowStrictMode {
601 
602         private static int sSetThreadPolicyCount;
603 
604         @Resetter
reset()605         public static void reset() {
606             sSetThreadPolicyCount = 0;
607         }
608 
609         @Implementation
setThreadPolicy(final StrictMode.ThreadPolicy policy)610         protected static void setThreadPolicy(final StrictMode.ThreadPolicy policy) {
611             sSetThreadPolicyCount++;
612         }
613 
isThreadPolicyOverridden()614         private static boolean isThreadPolicyOverridden() {
615             return sSetThreadPolicyCount != 0;
616         }
617     }
618 }
619