1 /* 2 * Copyright (C) 2016 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 package android.provider.cts; 18 19 import android.annotation.Nullable; 20 import android.content.ContentResolver; 21 import android.content.ContentUris; 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.database.ContentObserver; 25 import android.database.Cursor; 26 import android.net.Uri; 27 import android.provider.BlockedNumberContract; 28 import android.provider.BlockedNumberContract.BlockedNumbers; 29 30 import junit.framework.Assert; 31 32 import java.util.ArrayList; 33 import java.util.concurrent.CountDownLatch; 34 import java.util.concurrent.TimeUnit; 35 36 /** 37 * CTS tests for blockednumber provider accessed through {@link BlockedNumberContract}. 38 */ 39 // To run the tests in this file w/o running all the cts tests: 40 // make cts 41 // cts-tradefed 42 // run cts -m CtsProviderTestCases --test android.provider.cts.BlockedNumberContractTest 43 public class BlockedNumberContractTest extends TestCaseThatRunsIfTelephonyIsEnabled { 44 private ContentResolver mContentResolver; 45 private Context mContext; 46 private ArrayList<Uri> mAddedUris; 47 48 private static final String[] BLOCKED_NUMBERS_PROJECTION = new String[]{ 49 BlockedNumbers.COLUMN_ORIGINAL_NUMBER, 50 BlockedNumbers.COLUMN_E164_NUMBER}; 51 52 @Override 53 protected void setUp() throws Exception { 54 super.setUp(); 55 mContext = getInstrumentation().getContext(); 56 mContentResolver = mContext.getContentResolver(); 57 mAddedUris = new ArrayList<>(); 58 } 59 60 @Override 61 protected void tearDown() throws Exception { 62 for (Uri row : mAddedUris) { 63 mContentResolver.delete(row, null, null); 64 } 65 mAddedUris.clear(); 66 setDefaultSmsApp(false); 67 68 super.tearDown(); 69 } 70 71 public void testProviderInteractionsAsRegularApp_fails() { 72 try { 73 mAddedUris.add(mContentResolver.insert( 74 BlockedNumbers.CONTENT_URI, getContentValues("1234567890"))); 75 fail("Should throw SecurityException"); 76 } catch (SecurityException expected) { 77 } 78 79 try { 80 mContentResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 81 fail("Should throw SecurityException"); 82 } catch (SecurityException expected) { 83 } 84 85 try { 86 mContentResolver.update( 87 BlockedNumbers.CONTENT_URI, getContentValues("123"), null, null); 88 fail("Should throw SecurityException"); 89 } catch (SecurityException expected) { 90 } 91 92 try { 93 BlockedNumberContract.isBlocked(mContext, "123"); 94 fail("Should throw SecurityException"); 95 } catch (SecurityException expected) { 96 } 97 98 try { 99 BlockedNumberContract.unblock(mContext, "1234567890"); 100 fail("Should throw SecurityException"); 101 } catch (SecurityException expected) { 102 } 103 104 assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mContext)); 105 } 106 107 public void testGetType() throws Exception { 108 assertEquals(BlockedNumbers.CONTENT_TYPE, 109 mContentResolver.getType(BlockedNumbers.CONTENT_URI)); 110 assertEquals(BlockedNumbers.CONTENT_ITEM_TYPE, 111 mContentResolver.getType( 112 ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, 0))); 113 114 assertNull(mContentResolver.getType(BlockedNumberContract.AUTHORITY_URI)); 115 } 116 117 public void testInsertAndBlockCheck_succeeds() throws Exception { 118 setDefaultSmsApp(true); 119 120 assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mContext)); 121 122 assertInsertBlockedNumberSucceeds("1234567890", null); 123 // Attempting to insert a duplicate replaces the existing entry. 124 assertInsertBlockedNumberSucceeds("1234567890", "+812345678901"); 125 assertInsertBlockedNumberSucceeds("1234567890", null); 126 127 assertTrue(BlockedNumberContract.isBlocked(mContext, "1234567890")); 128 assertFalse(BlockedNumberContract.isBlocked(mContext, "2234567890")); 129 130 assertInsertBlockedNumberSucceeds("2345678901", "+12345678901"); 131 assertTrue(BlockedNumberContract.isBlocked(mContext, "2345678901")); 132 assertTrue(BlockedNumberContract.isBlocked(mContext, "+12345678901")); 133 134 assertInsertBlockedNumberSucceeds("1234 (at) abcd.com", null); 135 assertTrue(BlockedNumberContract.isBlocked(mContext, "1234 (at) abcd.com")); 136 137 assertInsertBlockedNumberSucceeds("2345 (at) abcd.com", null); 138 assertTrue(BlockedNumberContract.isBlocked(mContext, "2345 (at) abcd.com")); 139 140 assertFalse(BlockedNumberContract.isBlocked(mContext, "9999 (at) abcd.com")); 141 assertFalse(BlockedNumberContract.isBlocked(mContext, "random string")); 142 } 143 144 public void testUnblock_succeeds() throws Exception { 145 setDefaultSmsApp(true); 146 147 // Unblocking non-existent blocked number should return 0. 148 assertEquals(0, BlockedNumberContract.unblock(mContext, "6501004000")); 149 150 assertInsertBlockedNumberSucceeds("6501004000", null); 151 assertEquals(1, BlockedNumberContract.unblock(mContext, "6501004000")); 152 assertFalse(BlockedNumberContract.isBlocked(mContext, "(650)1004000")); 153 154 assertInsertBlockedNumberSucceeds("1234 (at) abcd.com", null); 155 assertEquals(1, BlockedNumberContract.unblock(mContext, "1234 (at) abcd.com")); 156 assertFalse(BlockedNumberContract.isBlocked(mContext, "1234 (at) abcd.com")); 157 } 158 159 public void testInsert_failsWithInvalidInputs() throws Exception { 160 setDefaultSmsApp(true); 161 162 try { 163 ContentValues cv = new ContentValues(); 164 cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234"); 165 mAddedUris.add(mContentResolver.insert( 166 ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, 1), 167 new ContentValues())); 168 fail("Should throw IllegalArgumentException."); 169 } catch (IllegalArgumentException expected) { 170 assertTrue(expected.getMessage().contains("Unsupported URI")); 171 } 172 173 try { 174 mAddedUris.add( 175 mContentResolver.insert(BlockedNumbers.CONTENT_URI, new ContentValues())); 176 fail("Should throw IllegalArgumentException."); 177 } catch (IllegalArgumentException expected) { 178 assertTrue(expected.getMessage().contains("Missing a required column")); 179 } 180 181 try { 182 ContentValues cv = new ContentValues(); 183 cv.put(BlockedNumbers.COLUMN_E164_NUMBER, "+1234"); 184 mAddedUris.add(mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv)); 185 fail("Should throw IllegalArgumentException."); 186 } catch (IllegalArgumentException expected) { 187 assertTrue(expected.getMessage().contains("Missing a required column")); 188 } 189 190 try { 191 ContentValues cv = new ContentValues(); 192 cv.put(BlockedNumbers.COLUMN_ID, "1"); 193 mAddedUris.add(mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv)); 194 fail("Should throw IllegalArgumentException."); 195 } catch (IllegalArgumentException expected) { 196 assertTrue(expected.getMessage().contains("must not be specified")); 197 } 198 } 199 200 public void testUpdate_isUnsupported() throws Exception { 201 setDefaultSmsApp(true); 202 try { 203 mContentResolver.update( 204 BlockedNumbers.CONTENT_URI, getContentValues("123"), null, null); 205 fail("Should throw UnsupportedOperationException"); 206 } catch (UnsupportedOperationException expected) { 207 } 208 } 209 210 public void testIsBlocked_returnsFalseForNullAndEmpty() throws Exception { 211 setDefaultSmsApp(true); 212 assertFalse(BlockedNumberContract.isBlocked(mContext, null)); 213 assertFalse(BlockedNumberContract.isBlocked(mContext, "")); 214 } 215 216 public void testDelete() throws Exception { 217 setDefaultSmsApp(true); 218 219 assertInsertBlockedNumberSucceeds("12345", "+112345"); 220 assertInsertBlockedNumberSucceeds("012345", "+112345"); 221 assertEquals(2, 222 mContentResolver.delete( 223 BlockedNumbers.CONTENT_URI, 224 BlockedNumbers.COLUMN_E164_NUMBER + "= ?", 225 new String[] {"+112345"})); 226 227 assertInsertBlockedNumberSucceeds("12345", ""); 228 assertEquals(1, 229 mContentResolver.delete( 230 BlockedNumbers.CONTENT_URI, 231 BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?", 232 new String[] {"12345"})); 233 234 Uri insertedUri = assertInsertBlockedNumberSucceeds("12345", ""); 235 assertEquals(1, 236 mContentResolver.delete( 237 BlockedNumbers.CONTENT_URI, 238 BlockedNumbers.COLUMN_ID + "= ?", 239 new String[] {Long.toString(ContentUris.parseId(insertedUri))})); 240 241 insertedUri = assertInsertBlockedNumberSucceeds("12345", ""); 242 assertEquals(1, 243 mContentResolver.delete( 244 ContentUris.withAppendedId( 245 BlockedNumbers.CONTENT_URI, ContentUris.parseId(insertedUri)), 246 null, null)); 247 248 insertedUri = assertInsertBlockedNumberSucceeds("12345", ""); 249 assertEquals(1, mContentResolver.delete(insertedUri, null, null)); 250 251 assertEquals(0, 252 mContentResolver.delete( 253 BlockedNumbers.CONTENT_URI, 254 BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?", 255 new String[] {"12345"})); 256 } 257 258 public void testDelete_failsOnInvalidInputs() throws Exception { 259 setDefaultSmsApp(true); 260 261 try { 262 mContentResolver.delete(Uri.parse("foobar"), null, null); 263 fail("Should throw IllegalArgumentException"); 264 } catch (IllegalArgumentException expected) { 265 } 266 267 Uri insertedUri = assertInsertBlockedNumberSucceeds("12345", ""); 268 try { 269 mContentResolver.delete( 270 insertedUri, 271 BlockedNumbers.COLUMN_E164_NUMBER + "= ?", 272 new String[] {"+112345"}); 273 fail("Should throw IllegalArgumentException"); 274 } catch (IllegalArgumentException expected) { 275 assertTrue(expected.getMessage().contains("selection must be null")); 276 } 277 } 278 279 public void testProviderNotifiesChangesUsingContentObserver() throws Exception { 280 setDefaultSmsApp(true); 281 282 Cursor cursor = mContentResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 283 284 final CountDownLatch latch = new CountDownLatch(2); 285 ContentObserver contentObserver = new ContentObserver(null) { 286 @Override 287 public void onChange(boolean selfChange) { 288 Assert.assertFalse(selfChange); 289 latch.notify(); 290 } 291 }; 292 cursor.registerContentObserver(contentObserver); 293 294 try { 295 Uri uri = assertInsertBlockedNumberSucceeds("12345", ""); 296 mContentResolver.delete(uri, null, null); 297 latch.await(10, TimeUnit.SECONDS); 298 } catch (Exception e) { 299 fail(e.toString()); 300 } finally { 301 cursor.unregisterContentObserver(contentObserver); 302 } 303 } 304 305 public void testAccessingNonExistentMethod_fails() throws Exception { 306 setDefaultSmsApp(true); 307 308 try { 309 mContext.getContentResolver() 310 .call(BlockedNumberContract.AUTHORITY_URI, "nonExistentMethod", "1234", null); 311 fail("Should throw IllegalArgumentException"); 312 } catch (IllegalArgumentException expected) { 313 assertTrue(expected.getMessage().contains("Unsupported method")); 314 } 315 } 316 317 private Uri assertInsertBlockedNumberSucceeds( 318 String originalNumber, @Nullable String e164Number) { 319 ContentValues cv = new ContentValues(); 320 cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, originalNumber); 321 if (e164Number != null) { 322 cv.put(BlockedNumbers.COLUMN_E164_NUMBER, e164Number); 323 } 324 Uri insertedUri = mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv); 325 mAddedUris.add(insertedUri); 326 327 Cursor cursor = mContentResolver.query( 328 BlockedNumbers.CONTENT_URI, 329 BLOCKED_NUMBERS_PROJECTION, 330 BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?", 331 new String[]{originalNumber}, 332 null); 333 assertTrue(cursor.moveToFirst()); 334 335 assertEquals(originalNumber, cursor.getString(0)); 336 if (e164Number != null) { 337 assertEquals(e164Number, cursor.getString(1)); 338 } 339 cursor.close(); 340 return insertedUri; 341 } 342 343 private ContentValues getContentValues(String originalNumber) { 344 ContentValues cv = new ContentValues(); 345 cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, originalNumber); 346 return cv; 347 } 348 349 private void setDefaultSmsApp(boolean setToSmsApp) throws Exception { 350 ProviderTestUtils.setDefaultSmsApp( 351 setToSmsApp, mContext.getPackageName(), getInstrumentation().getUiAutomation()); 352 } 353 } 354