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