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.Mockito.spy; 25 26 import android.app.ApplicationPackageManager; 27 import android.content.ComponentName; 28 import android.content.ContentResolver; 29 import android.content.Context; 30 import android.net.Uri; 31 import android.provider.SettingsSlicesContract; 32 import android.view.accessibility.AccessibilityManager; 33 34 import com.android.settings.search.SearchFeatureProvider; 35 import com.android.settings.search.SearchFeatureProviderImpl; 36 import com.android.settings.testutils.DatabaseTestUtils; 37 import com.android.settings.testutils.FakeFeatureFactory; 38 import com.android.settings.testutils.FakeIndexProvider; 39 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 40 import com.android.settings.testutils.shadow.ShadowLockPatternUtils; 41 import com.android.settings.testutils.shadow.ShadowUserManager; 42 import com.android.settings.testutils.shadow.ShadowUtils; 43 import com.android.settingslib.search.SearchIndexableData; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.robolectric.RobolectricTestRunner; 50 import org.robolectric.RuntimeEnvironment; 51 import org.robolectric.annotation.Config; 52 import org.robolectric.annotation.Implementation; 53 import org.robolectric.annotation.Implements; 54 import org.robolectric.shadow.api.Shadow; 55 import org.robolectric.shadows.ShadowAccessibilityManager; 56 57 import java.util.ArrayList; 58 import java.util.List; 59 import java.util.Locale; 60 61 @RunWith(RobolectricTestRunner.class) 62 @Config(shadows = {ShadowUserManager.class, ShadowUtils.class, 63 SlicesDatabaseAccessorTest.ShadowApplicationPackageManager.class, 64 ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class}) 65 public class SlicesDatabaseAccessorTest { 66 67 68 private Context mContext; 69 private SlicesDatabaseAccessor mAccessor; 70 71 @Before setUp()72 public void setUp() { 73 mContext = RuntimeEnvironment.application; 74 ShadowUserManager.getShadow().setIsAdminUser(true); 75 mAccessor = spy(new SlicesDatabaseAccessor(mContext)); 76 SlicesDatabaseHelper.getInstance(mContext).setIndexedState(); 77 78 // Register the fake a11y Service 79 ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract( 80 RuntimeEnvironment.application.getSystemService(AccessibilityManager.class)); 81 shadowAccessibilityManager.setInstalledAccessibilityServiceList(new ArrayList<>()); 82 } 83 84 @After cleanUp()85 public void cleanUp() { 86 DatabaseTestUtils.clearDb(mContext); 87 } 88 89 @Test testGetSliceDataFromKey_validKey_validSliceReturned()90 public void testGetSliceDataFromKey_validKey_validSliceReturned() { 91 String key = "key"; 92 SliceTestUtils.insertSliceToDb(mContext, key); 93 94 SliceData data = mAccessor.getSliceDataFromKey(key); 95 96 assertThat(data.getKey()).isEqualTo(key); 97 assertThat(data.getTitle()).isEqualTo(SliceTestUtils.FAKE_TITLE); 98 assertThat(data.getSummary()).isEqualTo(SliceTestUtils.FAKE_SUMMARY); 99 assertThat(data.getScreenTitle()).isEqualTo(SliceTestUtils.FAKE_SCREEN_TITLE); 100 assertThat(data.getKeywords()).isEqualTo(SliceTestUtils.FAKE_KEYWORDS); 101 assertThat(data.getIconResource()).isEqualTo(SliceTestUtils.FAKE_ICON); 102 assertThat(data.getFragmentClassName()).isEqualTo(SliceTestUtils.FAKE_FRAGMENT_NAME); 103 assertThat(data.getUri()).isNull(); 104 assertThat(data.getPreferenceController()).isEqualTo(SliceTestUtils.FAKE_CONTROLLER_NAME); 105 assertThat(data.getUnavailableSliceSubtitle()).isNull(); 106 } 107 108 @Test testGetSliceDataFromKey_allowDynamicSummary_validSliceReturned()109 public void testGetSliceDataFromKey_allowDynamicSummary_validSliceReturned() { 110 String key = "key"; 111 SliceTestUtils.insertSliceToDb(mContext, key, true /* isPlatformSlice */, 112 null /* customizedUnavailableSliceSubtitle */); 113 114 SliceData data = mAccessor.getSliceDataFromKey(key); 115 116 assertThat(data.getKey()).isEqualTo(key); 117 assertThat(data.getTitle()).isEqualTo(SliceTestUtils.FAKE_TITLE); 118 assertThat(data.getSummary()).isEqualTo(SliceTestUtils.FAKE_SUMMARY); 119 assertThat(data.getScreenTitle()).isEqualTo(SliceTestUtils.FAKE_SCREEN_TITLE); 120 assertThat(data.getKeywords()).isEqualTo(SliceTestUtils.FAKE_KEYWORDS); 121 assertThat(data.getIconResource()).isEqualTo(SliceTestUtils.FAKE_ICON); 122 assertThat(data.getFragmentClassName()).isEqualTo(SliceTestUtils.FAKE_FRAGMENT_NAME); 123 assertThat(data.getUri()).isNull(); 124 assertThat(data.getPreferenceController()).isEqualTo(SliceTestUtils.FAKE_CONTROLLER_NAME); 125 } 126 127 @Test(expected = IllegalStateException.class) testGetSliceDataFromKey_invalidKey_errorThrown()128 public void testGetSliceDataFromKey_invalidKey_errorThrown() { 129 String key = "key"; 130 131 mAccessor.getSliceDataFromKey(key); 132 } 133 134 @Test testGetSliceFromUri_validUri_validSliceReturned()135 public void testGetSliceFromUri_validUri_validSliceReturned() { 136 final String key = "key"; 137 SliceTestUtils.insertSliceToDb(mContext, key); 138 139 final Uri uri = new Uri.Builder() 140 .scheme(ContentResolver.SCHEME_CONTENT) 141 .authority(SettingsSliceProvider.SLICE_AUTHORITY) 142 .appendPath("action") 143 .appendPath(key) 144 .build(); 145 146 SliceData data = mAccessor.getSliceDataFromUri(uri); 147 148 assertThat(data.getKey()).isEqualTo(key); 149 assertThat(data.getTitle()).isEqualTo(SliceTestUtils.FAKE_TITLE); 150 assertThat(data.getSummary()).isEqualTo(SliceTestUtils.FAKE_SUMMARY); 151 assertThat(data.getScreenTitle()).isEqualTo(SliceTestUtils.FAKE_SCREEN_TITLE); 152 assertThat(data.getKeywords()).isEqualTo(SliceTestUtils.FAKE_KEYWORDS); 153 assertThat(data.getIconResource()).isEqualTo(SliceTestUtils.FAKE_ICON); 154 assertThat(data.getFragmentClassName()).isEqualTo(SliceTestUtils.FAKE_FRAGMENT_NAME); 155 assertThat(data.getUri()).isEqualTo(uri); 156 assertThat(data.getPreferenceController()).isEqualTo(SliceTestUtils.FAKE_CONTROLLER_NAME); 157 } 158 159 @Test(expected = IllegalStateException.class) testGetSliceFromUri_invalidUri_errorThrown()160 public void testGetSliceFromUri_invalidUri_errorThrown() { 161 final Uri uri = new Uri.Builder() 162 .scheme(ContentResolver.SCHEME_CONTENT) 163 .authority(SettingsSliceProvider.SLICE_AUTHORITY) 164 .appendPath("intent") 165 .appendPath("durr") 166 .build(); 167 mAccessor.getSliceDataFromUri(uri); 168 } 169 170 @Test getDescendantUris_platformSlice_doesNotReturnOEMSlice()171 public void getDescendantUris_platformSlice_doesNotReturnOEMSlice() { 172 final String key = "oem_key"; 173 SliceTestUtils.insertSliceToDb(mContext, key, false /* isPlatformSlice */, 174 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 175 final List<Uri> keys = mAccessor.getSliceUris(SettingsSlicesContract.AUTHORITY, 176 true /* isPublicSlice */); 177 178 assertThat(keys).isEmpty(); 179 } 180 181 @Test getDescendantUris_oemSlice_doesNotReturnPlatformSlice()182 public void getDescendantUris_oemSlice_doesNotReturnPlatformSlice() { 183 final String key = "platform_key"; 184 SliceTestUtils.insertSliceToDb(mContext, key, true /* isPlatformSlice */, 185 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 186 final List<Uri> keys = mAccessor.getSliceUris(SettingsSliceProvider.SLICE_AUTHORITY, 187 true /* isPublicSlice */); 188 189 assertThat(keys).isEmpty(); 190 } 191 192 @Test getDescendantUris_oemSlice_returnsOEMUriDescendant()193 public void getDescendantUris_oemSlice_returnsOEMUriDescendant() { 194 final String key = "oem_key"; 195 SliceTestUtils.insertSliceToDb(mContext, key, false /* isPlatformSlice */, 196 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 197 final List<Uri> keys = mAccessor.getSliceUris(SettingsSliceProvider.SLICE_AUTHORITY, 198 true /* isPublicSlice */); 199 200 assertThat(keys).containsExactly( 201 Uri.parse("content://com.android.settings.slices/action/oem_key")); 202 } 203 204 @Test getDescendantUris_platformSlice_returnsPlatformUriDescendant()205 public void getDescendantUris_platformSlice_returnsPlatformUriDescendant() { 206 final String key = "platform_key"; 207 SliceTestUtils.insertSliceToDb(mContext, key, true /* isPlatformSlice */, 208 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 209 final List<Uri> keys = mAccessor.getSliceUris(SettingsSlicesContract.AUTHORITY, 210 true /* isPublicSlice */); 211 212 assertThat(keys).containsExactly( 213 Uri.parse("content://android.settings.slices/action/platform_key")); 214 } 215 216 @Test getSliceUris_publicSlice_returnPublicUri()217 public void getSliceUris_publicSlice_returnPublicUri() { 218 SliceTestUtils.insertSliceToDb(mContext, "test_public", false /* isPlatformSlice */, 219 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 220 SliceTestUtils.insertSliceToDb(mContext, "test_private", false /* isPlatformSlice */, 221 null /* customizedUnavailableSliceSubtitle */, false /* isPublicSlice */); 222 final Uri expectedUri = new Uri.Builder() 223 .scheme(SCHEME_CONTENT) 224 .authority(SettingsSliceProvider.SLICE_AUTHORITY) 225 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) 226 .appendPath("test_public") 227 .build(); 228 229 final List<Uri> uri = mAccessor.getSliceUris(SettingsSliceProvider.SLICE_AUTHORITY, true); 230 231 assertThat(uri).containsExactly(expectedUri); 232 } 233 234 @Test getSliceUris_nonPublicSlice_returnNonPublicUri()235 public void getSliceUris_nonPublicSlice_returnNonPublicUri() { 236 SliceTestUtils.insertSliceToDb(mContext, "test_public", false /* isPlatformSlice */, 237 null /* customizedUnavailableSliceSubtitle */, true /* isPublicSlice */); 238 SliceTestUtils.insertSliceToDb(mContext, "test_private", false /* isPlatformSlice */, 239 null /* customizedUnavailableSliceSubtitle */, false /* isPublicSlice */); 240 final Uri expectedUri = new Uri.Builder() 241 .scheme(SCHEME_CONTENT) 242 .authority(SettingsSliceProvider.SLICE_AUTHORITY) 243 .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) 244 .appendPath("test_private") 245 .build(); 246 247 final List<Uri> uri = mAccessor.getSliceUris(SettingsSliceProvider.SLICE_AUTHORITY, false); 248 249 assertThat(uri).containsExactly(expectedUri); 250 } 251 252 @Test 253 @Config(qualifiers = "mcc999") getSliceKeys_indexesDatabase()254 public void getSliceKeys_indexesDatabase() { 255 // Force new indexing 256 Locale.setDefault(new Locale("ca")); 257 final SearchFeatureProvider provider = new SearchFeatureProviderImpl(); 258 final SlicesFeatureProvider sliceProvider = new SlicesFeatureProviderImpl(); 259 final FakeFeatureFactory factory = FakeFeatureFactory.setupForTest(); 260 factory.searchFeatureProvider = provider; 261 factory.slicesFeatureProvider = sliceProvider; 262 // Fake the indexable list. 263 provider.getSearchIndexableResources().getProviderValues().clear(); 264 provider.getSearchIndexableResources().getProviderValues().add( 265 new SearchIndexableData(FakeIndexProvider.class, 266 FakeIndexProvider.SEARCH_INDEX_DATA_PROVIDER)); 267 268 final SlicesDatabaseAccessor accessor = new SlicesDatabaseAccessor(mContext); 269 final List<Uri> keys = accessor.getSliceUris(SettingsSliceProvider.SLICE_AUTHORITY, 270 true /* isPublicSlice */); 271 272 assertThat(keys).isNotEmpty(); 273 } 274 275 @Test testGetSliceDataFromKey_defaultUnavailableSlice_validSliceReturned()276 public void testGetSliceDataFromKey_defaultUnavailableSlice_validSliceReturned() { 277 String key = "key"; 278 SliceTestUtils.insertSliceToDb(mContext, key, true /* isPlatformSlice */, 279 null /* customizedUnavailableSliceSubtitle */); 280 281 SliceData data = mAccessor.getSliceDataFromKey(key); 282 283 assertThat(data.getKey()).isEqualTo(key); 284 assertThat(data.getTitle()).isEqualTo(SliceTestUtils.FAKE_TITLE); 285 assertThat(data.getSummary()).isEqualTo(SliceTestUtils.FAKE_SUMMARY); 286 assertThat(data.getScreenTitle()).isEqualTo(SliceTestUtils.FAKE_SCREEN_TITLE); 287 assertThat(data.getKeywords()).isEqualTo(SliceTestUtils.FAKE_KEYWORDS); 288 assertThat(data.getIconResource()).isEqualTo(SliceTestUtils.FAKE_ICON); 289 assertThat(data.getFragmentClassName()).isEqualTo(SliceTestUtils.FAKE_FRAGMENT_NAME); 290 assertThat(data.getUri()).isNull(); 291 assertThat(data.getPreferenceController()).isEqualTo(SliceTestUtils.FAKE_CONTROLLER_NAME); 292 assertThat(data.getUnavailableSliceSubtitle()).isNull(); 293 } 294 295 @Test testGetSliceDataFromKey_customizeSubtitleOfUnavailableSlice_validSliceReturned()296 public void testGetSliceDataFromKey_customizeSubtitleOfUnavailableSlice_validSliceReturned() { 297 String key = "key"; 298 String subtitle = "subtitle"; 299 SliceTestUtils.insertSliceToDb(mContext, key, true /* isPlatformSlice */, subtitle); 300 301 SliceData data = mAccessor.getSliceDataFromKey(key); 302 303 assertThat(data.getKey()).isEqualTo(key); 304 assertThat(data.getTitle()).isEqualTo(SliceTestUtils.FAKE_TITLE); 305 assertThat(data.getSummary()).isEqualTo(SliceTestUtils.FAKE_SUMMARY); 306 assertThat(data.getScreenTitle()).isEqualTo(SliceTestUtils.FAKE_SCREEN_TITLE); 307 assertThat(data.getKeywords()).isEqualTo(SliceTestUtils.FAKE_KEYWORDS); 308 assertThat(data.getIconResource()).isEqualTo(SliceTestUtils.FAKE_ICON); 309 assertThat(data.getFragmentClassName()).isEqualTo(SliceTestUtils.FAKE_FRAGMENT_NAME); 310 assertThat(data.getUri()).isNull(); 311 assertThat(data.getPreferenceController()).isEqualTo(SliceTestUtils.FAKE_CONTROLLER_NAME); 312 assertThat(data.getUnavailableSliceSubtitle()).isEqualTo(subtitle); 313 } 314 315 @Implements(ApplicationPackageManager.class) 316 public static class ShadowApplicationPackageManager extends 317 org.robolectric.shadows.ShadowApplicationPackageManager { 318 319 @Implementation getInstantAppResolverSettingsComponent()320 protected ComponentName getInstantAppResolverSettingsComponent() { 321 return null; 322 } 323 } 324 } 325