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